[英]What is the equivalent of timestamp/rowversion (SQL Server) with PostgreSQL
[英]SQL Server : RowVersion equivalent in Oracle
Oracle 是否具有与SQL 服务器的RowVersion
相似的数据类型?
当您插入或更新一行时,相应的 Version 列(类型为RowVersion
)会自动更新。
是一种公开数据库中自动生成的唯一二进制数的数据类型。 rowversion 通常用作版本标记表行的机制。 存储大小为 8 个字节。 rowversion 数据类型只是一个递增的数字,不保留日期或时间。
每个数据库都有一个计数器,该计数器会随着在数据库中包含 rowversion 列的表上执行的每个插入或更新操作而递增。 此计数器是数据库行版本。 这跟踪数据库中的相对时间,而不是可以与时钟关联的实际时间。 一个表只能有一个 rowversion 列。 每次修改或插入带有 rowversion 列的行时,都会将递增的数据库 rowversion 值插入到 rowversion 列中。
您可以使用一行的 rowversion 列轻松确定该行中的任何值自上次读取以来是否已更改。 如果对该行进行了任何更改,则会更新 rowversion 值。 如果没有对该行进行任何更改,则 rowversion 值与之前读取时的值相同。
您可以向表中添加一个 rowversion 列,以在多个用户同时更新行时帮助维护数据库的完整性。 您可能还想知道在不重新查询表的情况下更新了多少行和哪些行。
我们正在设计数据 model 和 oracle,并希望使用版本列来管理并发。
我也想知道Oracle世界有没有更好的方法。
Oracle有SCN(系统变更号): http : //docs.oracle.com/cd/E11882_01/server.112/e10713/transact.htm#CNCPT039
系统更改编号(SCN)是Oracle数据库使用的逻辑内部时间戳。 SCN对数据库中发生的事件进行排序,这是满足事务的ACID属性所必需的。 Oracle数据库使用SCN标记SCN,在此之前已知所有更改都在磁盘上,以便恢复避免应用不必要的重做。 数据库还使用SCN标记一组数据不存在重做的点,以便可以停止恢复。
SCN以单调递增的顺序发生。 Oracle数据库可以像时钟一样使用SCN,因为观察到的SCN表示逻辑时间点,重复观察返回相等或更大的值。 如果一个事件的SCN低于另一个事件,则它在较早的时间发生在数据库中。 多个事件可能共享相同的SCN,这意味着它们与数据库同时发生。
每笔交易都有一个SCN。 例如,如果事务更新了一行,则数据库会记录发生此更新的SCN。 此事务中的其他修改具有相同的SCN。 当事务提交时,数据库会记录此提交的SCN。
使用ORA_ROWSCN伪列来检查行的当前SCN:
http://docs.oracle.com/cd/B28359_01/server.111/b28286/pseudocolumns007.htm#SQLRF51145
一个例子:
SELECT ora_rowscn, t.* From test t;
演示 - > http://www.sqlfiddle.com/#!4/535bc/1
(在SQLFiddle上显式提交显然不起作用 - 在真实数据库上,每次提交都会增加SCN)。
关于“真实”数据库的示例:
CREATE TABLE test(
id int,
value int
);
INSERT INTO test VALUES(1,0);
COMMIT;
SELECT ora_rowscn, t.* FROM test t;
ORA_ROWSCN ID VALUE
---------- ---------- ----------
3160728 1 0
UPDATE test SET value = value + 1 WHERE id = 1;
COMMIT;
SELECT ora_rowscn, t.* FROM test t;
ORA_ROWSCN ID VALUE
---------- ---------- ----------
3161657 1 1
UPDATE test SET value = value + 1 WHERE id = 1;
COMMIT;
SELECT ora_rowscn, t.* FROM test t;
ORA_ROWSCN ID VALUE
---------- ---------- ----------
3161695 1 2
如果知道事务的SCN,我们可以使用闪回查询来获取行的过去值:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_flashback.htm#g1026131
一个例子:
SELECT t.*,
versions_startscn, versions_starttime,
versions_endscn, versions_endtime,
versions_xid, versions_operation
FROM test VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE t;
ID VALUE VERSIONS_STARTSCN VERSIONS_STARTTIME VERSIONS_ENDSCN VERSIONS_ENDTIME VERSIONS_XID VERSIONS_OPERATION
---------- ---------- ----------------- ------------------- --------------- ------------------- ---------------- ------------------
1 2 3161695 13/12/10 08:19:39 06000300EA070000 U
1 1 3161657 13/12/10 08:18:39 3161695 13/12/10 08:19:39 06001200EA070000 U
1 0 3161657 13/12/10 08:18:39
SELECT t.*,
versions_startscn, versions_starttime,
versions_endscn, versions_endtime,
versions_xid, versions_operation
FROM test VERSIONS BETWEEN SCN 3161657 AND 3161657 t;
ID VALUE VERSIONS_STARTSCN VERSIONS_STARTTIME VERSIONS_ENDSCN VERSIONS_ENDTIME VERSIONS_XID VERSIONS_OPERATION
---------- ---------- ----------------- ------------------- --------------- ------------------- ---------------- ------------------
1 1 3161657 13/12/10 08:18:39 06001200EA070000 U
简单的答案是否定的 - 但是使用NUMBER列和触发器来设置/更新它很容易。
Oracle 11gR2的一个简单示例:
CREATE SEQUENCE global_rowversion_seq;
ALTER TABLE mytable1 ADD rowversion NUMBER;
ALTER TABLE mytable2 ADD rowversion NUMBER;
CREATE TRIGGER mytable1_biu
BEFORE INSERT OR UPDATE
ON mytable1
FOR EACH ROW
BEGIN
:NEW.rowversion := global_rowversion_seq.NEXTVAL;
END mytable1_biu;
CREATE TRIGGER mytable2_biu
BEFORE INSERT OR UPDATE
ON mytable2
FOR EACH ROW
BEGIN
:NEW.rowversion := global_rowversion_seq.NEXTVAL;
END mytable2_biu;
(如果您使用的是较早的Oracle版本,则必须使用查询完成触发器中的分配,例如:
SELECT global_rowversion_seq.NEXTVAL
INTO :NEW.rowversion
FROM dual;
现在,请记住,在某些情况下,由于使用相同序列的所有数据库插入/更新的争用,此设计可能在极端情况下(例如,具有极高插入/更新活动的数据库)具有性能影响。 当然,在这种情况下,你可能会首先避免触发器。
根据您使用rowversion列的方式,最好为每个表使用单独的序列。 当然,这意味着rowversion将不再是全局唯一的 - 但如果您只想将更改与表中的行进行比较,那么这样就可以了。
另一种方法是单独推进每一行的计数器 - 这不需要序列,并允许您检测行的更改(但不允许将任何行与另一行进行比较):
ALTER TABLE mytable ADD rowversion NUMBER;
CREATE TRIGGER mytable_biu
BEFORE INSERT OR UPDATE
ON mytable
FOR EACH ROW
BEGIN
:NEW.rowversion := NVL(:OLD.rowversion, 0) + 1;
END mytable_biu;
每行将插入rowversion = 1,然后对该行的后续更新将其增加到2,3等。
根据oracle文档,您可以使用ORA_ROWSCN,并使用“ROWDEPENDENCIES”进行oracle行级依赖关系跟踪。 不是每个物理数据块。
参考: https : //docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm
一个简单的 Timestamp 列是否适合跟踪一个用户何时对 Oracle 中的单个表进行 INSERT 或 UPDATE ? 为什么不简单地使用“时间戳”列作为 SQL Server 的“RowVersion”等效项?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.