Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 序列化插入_Sql Server_Oracle_Concurrency_Isolation Level_Table Locking - Fatal编程技术网

Sql server 序列化插入

Sql server 序列化插入,sql-server,oracle,concurrency,isolation-level,table-locking,Sql Server,Oracle,Concurrency,Isolation Level,Table Locking,如果这个问题的答案取决于DMB,我很想听听Oracle 11g或更高版本和SQL Server 2012的答案 我们有一个表,它有一个引用自身的外键: CREATE TABLE Versions ( Id INT IDENTITY(1,1) NOT NULL, [Date] DATETIME NOT NULL, BasedOnVersion INT NULL -- foreign key that references Versions ) 我们有将新记录插入Vers

如果这个问题的答案取决于DMB,我很想听听Oracle 11g或更高版本和SQL Server 2012的答案

我们有一个表,它有一个引用自身的外键:

CREATE TABLE Versions (
    Id INT IDENTITY(1,1) NOT NULL,
    [Date] DATETIME NOT NULL,
    BasedOnVersion INT NULL  -- foreign key that references Versions
)
我们有将新记录插入
Versions
表的存储过程。如果它们同时运行,我们需要确保没有两个版本引用相同的另一个版本,因此版本层次结构中不能有任何分叉(除非我们有意创建分叉):

在第二种情况下,我们有两个基于相同版本的版本

因此,我们需要一种序列化这两个事务的方法。首先,我们考虑使用
隔离级别SERIALIZABLE
,但是隔离级别对
插入没有任何影响,因此它们不是解决方案

另一种方法是在事务开始时获取
Versions
表上的锁。这可能适用于SQL Server,但不适用于Oracle,因为Oracle的
以独占模式锁定表
不会阻止事务2读取表


那么,对于这类问题,最好的解决方案是什么呢?

您可以使用版本序列。序列对于并发操作是安全的

所以,


似乎您是按照以下方式确定最新版本的:

 select MAX(ID) from Versions
因此,如果它包含在可序列化事务中(作为插入的一部分或单独),那么插入将是可序列化的

set transaction isolation level serializable

begin tran
    insert Versions (basedonversion)
    select MAX(ID) from Versions
commit tran 
这就是所谓的“丢失更新问题”,它有许多解决方案。并不是所有的锁都需要悲观锁

一种方法是修改“write”方法,在WHERE子句中使用一个谓词,如果当前版本与会话读取的版本不同,该谓词将阻止更新更新版本

i、 e

  • 事务1读取当前版本17
  • 事务2读取当前版本17
  • 事务1基于17写入新版本18
  • 事务2尝试写入新版本18,但
    更新v=18,其中v=17
    导致“0条记录已更新”,会话将此作为错误处理,例如“其他用户已修改此版本,请重新查询并重试”
  • 我早在2005年就写过这篇文章,列出了一些方法:

     select MAX(ID) from Versions
    
    set transaction isolation level serializable
    
    begin tran
        insert Versions (basedonversion)
        select MAX(ID) from Versions
    commit tran