select语句的独占锁和共享锁 - SQL Server

时间:2014-08-08 06:27:45

标签: sql sql-server locking shared isolation

我无法理解select在独占事务中的行为方式。请考虑以下情况 -

场景1 步骤1.1

create table Tmp(x int)
insert into Tmp values(1)

第1.2步 - 第1节

begin tran
set transaction isolation level serializable 
select * from Tmp

步骤1.3 - 会话2

select * from Tmp

即使第一次会话还没有完成,会话2也能够读取tmp表。我认为Tmp将具有独占锁,并且不应该在会话2中选择查询发出共享锁。并且它没有发生。我已确保默认隔离级别为READ COMMITED。

提前感谢您帮助我理解这种行为。

编辑:为什么我需要选择独占锁?

我有一个实际生成顺序值的SP。所以流程是 -

  1. 从表中读取最大值并在变量中存储值
  2. 更新表格设定值=值+ 1
  3. 此SP由几千个实例并行执行。如果两个实例同时执行SP,那么它们将读取相同的值并将更新值+ 1。虽然我希望每次执行都有顺序值。我认为只有当select也是独占锁的一部分时才有可能。

1 个答案:

答案 0 :(得分:0)

如果您希望事务可序列化,则必须在开始最外层事务之前更改该选项。所以你的第一个会话是不正确的,并且仍然在read committed(或任何其他级别对该会话有效)下运行。

但是即使你更正了语句的顺序,它仍然不会获得普通SELECT语句的独占锁。


如果您希望普通SELECT获得排他锁,则需要提出要求:

select * from Tmp with (XLOCK)

或者你需要执行一个实际需要独占锁的语句:

update Tmp set x = x

您的第一个会话不需要独占锁定,因为它不会更改数据。如果您的第一个(可序列化)会话已经运行完成并且已经回滚或提交,那么在第二个会话开始之前,该会话的结果仍然是相同的,因为您的第一个会话没有更改数据 - 所以"可序列化"交易的性质是正确的。