锁如何在insert ... select语句中工作?

两场会议中的两笔交易的运营项目与以下项目相同:

在会议1:

begin tran T1

   insert into Invoice with (item,OrderNumber) 

    select 'ItemA', max(OrderNumber)+1 

    from Orders

    where item='ItemA'

    waitfor delay '00:00:05'

commit T1

在会议2中:

begin tran T2

   insert into Invoice with (item,OrderNumber) 

    select 'ItemA', max(OrderNumber)+1 

    from Orders

    where item='ItemA'

commit T2

如果就这样,两个相同的行将被插入表Orders中。 但我希望在任一会话中的事务先完成,然后另一个事务可以读取新的最大值(OrderNumber),然后插入下一个值。 我将T1锁定为:

begin tran T1

   insert into Invoice with (item,OrderNumber) 

    select 'ItemA', max(OrderNumber)+1 

    from Orders with (holdlock)

    where item='ItemA'

    waitfor delay '00:00:05'

commit T1

SQl SERVER是否分配共享锁以便首先选择,因为它首先解析select语句然后分配独占锁来插入语句? 在两个会话中,锁具是如何相互作用的? 感谢任何提示


您可以使用可序列化的隔离级别来处理事务。

例如:

 set transaction isolation level serializable
 begin tran
    insert into Invoice with (item,OrderNumber) 
    select 'ItemA', max(OrderNumber)+1 
    from Orders
    where item='ItemA'

    waitfor delay '00:00:05'

 commit tran 

可串行化选项将提供以下事务功能:

  • 语句不能读取已被修改但尚未被其他事务处理的数据
  • 在当前事务完成之前,没有其他事务可以修改当前事务读取的数据
  • 其他事务不能插入具有键值的新行,这些键值落在当前事务中任何语句读取的键的范围内,直到当前事务完成。
  • 以上将适用于您的问题,但我会建议使用身份列而不是最大order_number + 1逻辑。 因此,将OrderNumber更改为表中的标识,并且当您读取数据时,请使用row_number编号按运算符中的Item计算订单编号,以下是一个示例查询:

      select Item, Row_Number() over(partition by Item order by OrderNumber) as OrderNumber
      from Invoice
    

    所以上面的查询会给出你需要的结果。


    你的最终目标是什么? 我不认为你不能在选择时停止带锁的插入,它只会锁定任何更新中的选定行。


    数据库锁定方案是任何数据库管理应用程序的组成部分 为了存储在数据库中的数据的完整性,不同的数据库供应商提供不同的锁定方案。 您应该检查以下链接First Link

    第二链接。 如果这些没有帮助,请让我知道,以便我可以进一步帮助您。

    链接地址: http://www.djcxy.com/p/5615.html

    上一篇: How do locks work in a insert...select statement?

    下一篇: SELECT FOR UPDATE with SQL Server