0

我无法理解 select 在排他事务中的行为方式。请考虑以下场景——</p>

方案 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

该 SP 由数千个实例并行执行。如果两个实例同时执行 SP,那么它们将读取相同的值并更新 value+1。虽然我希望每次执行都有顺序值。我认为只有当 select 也是独占锁的一部分时才有可能。

4

1 回答 1

0

如果您希望事务可序列化,则必须在开始最外层事务之前更改该选项。因此,您的第一个会话不正确,并且实际上仍在读取已提交(或对该会话有效的任何其他级别)下运行。

但是即使你更正了语句的顺序,它仍然不会为普通SELECT语句获取排他锁。


如果你想让plainSELECT获得一个排他锁,你需要请求它:

select * from Tmp with (XLOCK)

或者你需要执行一个实际上需要排他锁的语句:

update Tmp set x = x

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

于 2014-08-08T06:37:43.653 回答