等价于其他数据库中的`ora_rowscn`?

lee*_*d00 5 mysql postgresql sql-server data-versioning

Oracle 以外的其他数据库是否有ora_rowscnhttp://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm)等价物,或者您是否必须在您的字段、代码和存储过程中自己实现它们?

ora_rowscn是附加到使用某些特定设置创建的 Oracle 中所有表的伪列,在执行乐观离线锁定时使用

Pau*_*ite 2

据我了解这个问题,这种情况是用户从事务外部的数据库读取值,然后尝试更新。要求是数据库检测何时可能发生丢失更新。

SQL Server 不提供 Oracle 伪列的直接等效项,ora_rowscn因为它并不专门使用行版本控制来实现事务隔离级别(因此行版本控制信息并不总是存在)。尽管如此,有多种方法可以使用 SQL Server 实现乐观并发控制。

使用行版本

一种选择是向表中添加一rowversion列。通常,该列在所有表中都会被赋予相同的名称(例如RV)。一般的策略是在读取数据时读取该rowversion值,并在稍后更新该行时检查该值是否未更改:

CREATE TABLE dbo.Example
(
    SomeKey     integer PRIMARY KEY,
    SomeValue   integer NOT NULL,
    OtherValue  integer NOT NULL,
    RV          rowversion NOT NULL
);

INSERT dbo.Example
    (SomeKey, SomeValue, OtherValue)
VALUES
    (1, 100, 1000);

-- Read data
SELECT SomeValue, RV
FROM dbo.Example AS E
WHERE SomeKey = 1;

-- Time passes

-- Attempt update
UPDATE dbo.Example
SET SomeValue = 123
WHERE SomeKey = 1
AND RV = 0x0000000000273711;
Run Code Online (Sandbox Code Playgroud)

如果该行已被修改,则该UPDATE语句不会进行任何更改,并且不会返回任何错误或警告。由开发人员检查受该语句影响的行数,并采取适当的操作(例如重新读取源行,并警告用户存在冲突)。

使用乐观游标

服务器端游标经常用于我们正在讨论的场景中。SQL ServerOPTIMISTIC通过许多接口(例如API、ODBC、Native Client)包含对服务器端游标的本机支持。如果rowversion存在列,SQL Server 将使用它来实现乐观并发,而开发人员无需rowversion显式检索和检查该值。使用Transact-SQL光标来演示:

DECLARE UIcursor
    CURSOR GLOBAL
    SCROLL DYNAMIC
    OPTIMISTIC
FOR
    SELECT SomeValue
    FROM dbo.Example
    WHERE SomeKey = 1
    FOR UPDATE OF SomeValue;

OPEN UIcursor;

-- Read data
FETCH FIRST FROM UIcursor;

-- Time passes

-- Attempt update (note no rowversion reference needed)
UPDATE dbo.Example
SET SomeValue = 321
WHERE CURRENT OF UIcursor;
Run Code Online (Sandbox Code Playgroud)

如果自读取数据后该行已更改,则会返回警告和错误:

CREATE TABLE dbo.Example
(
    SomeKey     integer PRIMARY KEY,
    SomeValue   integer NOT NULL,
    OtherValue  integer NOT NULL,
    RV          rowversion NOT NULL
);

INSERT dbo.Example
    (SomeKey, SomeValue, OtherValue)
VALUES
    (1, 100, 1000);

-- Read data
SELECT SomeValue, RV
FROM dbo.Example AS E
WHERE SomeKey = 1;

-- Time passes

-- Attempt update
UPDATE dbo.Example
SET SomeValue = 123
WHERE SomeKey = 1
AND RV = 0x0000000000273711;
Run Code Online (Sandbox Code Playgroud)

如果表不包含rowversion,SQL Server 会透明地使用可靠的校验和来检测行更改。如果校验和比较失败,则会生成相同的警告和错误。使用rowversion比使用内部校验和更有效,但两者同样可靠。

请注意,真正的实现不太可能使用如上所示的全局 Transact-SQL 游标,但使用开发框架中可用的任何服务器端游标支持时,概念是相同的。