Oracle是否具有与SQL Server's RowVersion
类似的数据类型?
插入或更新行时,相应的“版本”列(类型为RowVersion
)会自动更新。
是一种公开自动生成的唯一二进制文件的数据类型 数据库中的数字。 rowversion通常用作机制 用于版本标记表行。存储大小为8个字节。该 rowversion数据类型只是一个递增的数字而不是 保留日期或时间。
每个数据库都有一个计数器,对于每个插入或增加一个计数器 在包含a的表上执行的更新操作 数据库中的rowversion列。这个计数器是数据库 rowversion。这会跟踪数据库中的相对时间,而不是数据库 可以与时钟关联的实际时间。一张桌子只能有 一个rowversion列。每次有一行rowversion列 被修改或插入,递增的数据库rowversion值是 插入rowversion列。
您可以使用行的rowversion列轻松确定是否 自上次读取以来,该行中的任何值都已更改。如果 如果对行进行任何更改,则会更新rowversion值。如果不 对行进行更改,rowversion值与其相同 以前读过。
您可以向表中添加rowversion列以帮助维护 多个用户在更新行时的数据库的完整性 同时。您可能还想知道有多少行和哪些行 更新后无需重新查询表格。
我们正在使用oracle设计数据模型,并希望使用Version列来管理并发。
我还想知道Oracle世界中是否有更好的方法。
答案 0 :(得分:16)
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
答案 1 :(得分:4)
简单的答案是否定的 - 但是使用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等等。
答案 2 :(得分:1)
根据oracle文档,您可以使用ORA_ROWSCN,并使用" ROWDEPENDENCIES"进行oracle行级依赖关系跟踪。不是每个物理数据块。
参考:https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm