简体   繁体   English

SQL 服务器:RowVersion 等效于 Oracle

[英]SQL Server : RowVersion equivalent in Oracle

Does Oracle has similar datatype to SQL Server's RowVersion ? Oracle 是否具有与SQL 服务器的RowVersion相似的数据类型?

When you insert or update a row, the corresponding Version column(which is of type RowVersion ) gets updated automatically.当您插入或更新一行时,相应的 Version 列(类型为RowVersion )会自动更新。

MSDN says about RowVersion :MSDN 说 RowVersion

  • Is a data type that exposes automatically generated, unique binary numbers within a database.是一种公开数据库中自动生成的唯一二进制数的数据类型。 rowversion is generally used as a mechanism for version-stamping table rows. rowversion 通常用作版本标记表行的机制。 The storage size is 8 bytes.存储大小为 8 个字节。 The rowversion data type is just an incrementing number and does not preserve a date or a time. rowversion 数据类型只是一个递增的数字,不保留日期或时间。

  • Each database has a counter that is incremented for each insert or update operation that is performed on a table that contains a rowversion column within the database.每个数据库都有一个计数器,该计数器会随着在数据库中包含 rowversion 列的表上执行的每个插入或更新操作而递增。 This counter is the database rowversion.此计数器是数据库行版本。 This tracks a relative time within a database, not an actual time that can be associated with a clock.这跟踪数据库中的相对时间,而不是可以与时钟关联的实际时间。 A table can have only one rowversion column.一个表只能有一个 rowversion 列。 Every time that a row with a rowversion column is modified or inserted, the incremented database rowversion value is inserted in the rowversion column.每次修改或插入带有 rowversion 列的行时,都会将递增的数据库 rowversion 值插入到 rowversion 列中。

  • You can use the rowversion column of a row to easily determine whether any value in the row has changed since the last time it was read.您可以使用一行的 rowversion 列轻松确定该行中的任何值自上次读取以来是否已更改。 If any change is made to the row, the rowversion value is updated.如果对该行进行了任何更改,则会更新 rowversion 值。 If no change is made to the row, the rowversion value is the same as when it was previously read.如果没有对该行进行任何更改,则 rowversion 值与之前读取时的值相同。

  • You can add a rowversion column to a table to help maintain the integrity of the database when multiple users are updating rows at the same time.您可以向表中添加一个 rowversion 列,以在多个用户同时更新行时帮助维护数据库的完整性。 You may also want to know how many rows and which rows were updated without re-querying the table.您可能还想知道在不重新查询表的情况下更新了多少行和哪些行。

We are designing a data model with oracle and would like to use Version column to manage concurrency.我们正在设计数据 model 和 oracle,并希望使用版本列来管理并发。

I would also like to know if there is better way in Oracle world.我也想知道Oracle世界有没有更好的方法。

Oracle has SCN (System Change Numbers): http://docs.oracle.com/cd/E11882_01/server.112/e10713/transact.htm#CNCPT039 Oracle有SCN(系统变更号): http//docs.oracle.com/cd/E11882_01/server.112/e10713/transact.htm#CNCPT039

A system change number (SCN) is a logical, internal time stamp used by Oracle Database. 系统更改编号(SCN)是Oracle数据库使用的逻辑内部时间戳。 SCNs order events that occur within the database, which is necessary to satisfy the ACID properties of a transaction. SCN对数据库中发生的事件进行排序,这是满足事务的ACID属性所必需的。 Oracle Database uses SCNs to mark the SCN before which all changes are known to be on disk so that recovery avoids applying unnecessary redo. Oracle数据库使用SCN标记SCN,在此之前已知所有更改都在磁盘上,以便恢复避免应用不必要的重做。 The database also uses SCNs to mark the point at which no redo exists for a set of data so that recovery can stop. 数据库还使用SCN标记一组数据不存在重做的点,以便可以停止恢复。

SCNs occur in a monotonically increasing sequence. SCN以单调递增的顺序发生。 Oracle Database can use an SCN like a clock because an observed SCN indicates a logical point in time and repeated observations return equal or greater values. Oracle数据库可以像时钟一样使用SCN,因为观察到的SCN表示逻辑时间点,重复观察返回相等或更大的值。 If one event has a lower SCN than another event, then it occurred at an earlier time with respect to the database. 如果一个事件的SCN低于另一个事件,则它在较早的时间发生在数据库中。 Several events may share the same SCN, which means that they occurred at the same time with respect to the database. 多个事件可能共享相同的SCN,这意味着它们与数据库同时发生。

Every transaction has an SCN. 每笔交易都有一个SCN。 For example, if a transaction updates a row, then the database records the SCN at which this update occurred. 例如,如果事务更新了一行,则数据库会记录发生此更新的SCN。 Other modifications in this transaction have the same SCN. 此事务中的其他修改具有相同的SCN。 When a transaction commits, the database records an SCN for this commit. 当事务提交时,数据库会记录此提交的SCN。


Use an ORA_ROWSCN pseudocolumn to examine current SCN of rows: 使用ORA_ROWSCN伪列来检查行的当前SCN:
http://docs.oracle.com/cd/B28359_01/server.111/b28286/pseudocolumns007.htm#SQLRF51145 http://docs.oracle.com/cd/B28359_01/server.111/b28286/pseudocolumns007.htm#SQLRF51145

An example: 一个例子:

SELECT ora_rowscn, t.* From test t;

Demo --> http://www.sqlfiddle.com/#!4/535bc/1 演示 - > http://www.sqlfiddle.com/#!4/535bc/1
(On SQLFiddle explicit commits apparently don't work - on a real database each commit increases SCN). (在SQLFiddle上显式提交显然不起作用 - 在真实数据库上,每次提交都会增加SCN)。


An example on a "real" database: 关于“真实”数据库的示例:

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 

If SCN of the transaction is know, we can use a flashback query to obtain a past value of the row: 如果知道事务的SCN,我们可以使用闪回查询来获取行的过去值:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_flashback.htm#g1026131 http://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_flashback.htm#g1026131

An example: 一个例子:

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                               

The simple answer is No - but it's easy to create one yourself with a NUMBER column and a trigger to set/update it. 简单的答案是否定的 - 但是使用NUMBER列和触发器来设置/更新它很容易。

A simple example for Oracle 11gR2: 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;

(If you're on an earlier Oracle version, the assignments in the triggers must be done with a query, eg: (如果您使用的是较早的Oracle版本,则必须使用查询完成触发器中的分配,例如:

  SELECT global_rowversion_seq.NEXTVAL
  INTO :NEW.rowversion
  FROM dual;

Now, keep in mind in some cases this design may have a performance impact in extreme situations (eg databases with extremely high insert/update activity) due to contention from all database inserts/updates using the same sequence. 现在,请记住,在某些情况下,由于使用相同序列的所有数据库插入/更新的争用,此设计可能在极端情况下(例如,具有极高插入/更新活动的数据库)具有性能影响。 Of course, in this circumstance you probably would avoid triggers in the first place anyway. 当然,在这种情况下,你可能会首先避免触发器。

Depending on how you use the rowversion column, it may be a good idea to use a separate sequence for each table instead. 根据您使用rowversion列的方式,最好为每个表使用单独的序列。 This would mean, of course, that rowversion would no longer be globally unique - but if you are only interested in comparing changes to rows within a table, then this would be fine. 当然,这意味着rowversion将不再是全局唯一的 - 但如果您只想将更改与表中的行进行比较,那么这样就可以了。

Another approach is to advance the counter for each row individually - this doesn't need a sequence and allows you to detect changes to a row (but does not allow comparing any row to another row): 另一种方法是单独推进每一行的计数器 - 这不需要序列,并允许您检测行的更改(但不允许将任何行与另一行进行比较):

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;

Each row will be inserted with rowversion = 1, then subsequent updates to that row will increment it to 2, 3, etc. 每行将插入rowversion = 1,然后对该行的后续更新将其增加到2,3等。

As per oracle Documentation you can use ORA_ROWSCN, and using "ROWDEPENDENCIES" to make oracle row-level dependency tracking. 根据oracle文档,您可以使用ORA_ROWSCN,并使用“ROWDEPENDENCIES”进行oracle行级依赖关系跟踪。 not per physical data block. 不是每个物理数据块。

Ref: https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm 参考: https//docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm

http://www.dba-oracle.com/t_row_scn_rowdependencies.htm http://www.dba-oracle.com/t_row_scn_rowdependencies.htm

Wouldn't a simple Timestamp column be appropriate to track when one user INSERTs or UPDATEs against a single table in Oracle ?一个简单的 Timestamp 列是否适合跟踪一个用户何时对 Oracle 中的单个表进行 INSERT 或 UPDATE ? Why not simply use a "Timestamp" column to act as a "RowVersion" equivalent from SQL Server ?为什么不简单地使用“时间戳”列作为 SQL Server 的“RowVersion”等效项?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM