select 语句的排它锁和共享锁 - SQL Server

问题描述 投票:0回答:1

我无法理解 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

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

sql sql-server locking shared isolation
1个回答
0
投票

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

但是即使你更正了语句的顺序,它仍然不会为普通的

SELECT

 语句获取独占锁。


如果你想让普通的

SELECT

获得独占锁,你需要请求它:

select * from Tmp with (XLOCK)

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

update Tmp set x = x

您的第一个会话不需要

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

© www.soinside.com 2019 - 2024. All rights reserved.