SQL Server 锁的排队机制

1、新建一个表,插入1010000数据:

create table test(id int identity(1,1) ,name varchar(600))
go

insert into test
values(replicate('a',600));
go 1010000

create index idx_test_id on test(id)

2、新开一个会话(A),运行如下语句,由于没有提交,所以会阻塞其他药修改相同数据的会话:

begin tran
	update test
	set name = replicate('f',500)
	where id = 100000

3、再新开一个会话(B),运行如下语句,由于需要修改id为 100000的数据,所以被上一个会话A阻塞了。

需要特别注意的是,在语句中使用了查询提示repeatableread,那么select语句对记录获取的S锁,只有在commit或rollback时,才会释放。

begin tran

select *
from test with(repeatableread)
where id >= 9000 and id <= 100000

select  sysdatetime()

4、再开一个会话(C),运行如下语句,由于需要修改id为100000的数据,所以被会话A阻塞了

begin tran

	update test
	set name = replicate('k',589)
	where id = 100000

	select  sysdatetime()

5、在会话A中,通过commit来提交事务,这个时候,会话B会马上返回结果,但会话C还是继续被阻塞,这个时候C被B会话阻塞。

接下来,在会话B中执行commit,于是会话C立即返回。

从以上的现象大致能看出,数据库锁中的队列机制,也就是当很多会话都需要访问相同的资源时,会有一个队列机制,一开始A对资源加上独占锁,获取到资源,但没有提交,所以没有释放资源上的锁。

会话B也需要访问相同的资源,由于会话需要读数据,所以需要加上共享锁,但由于共享锁和之前资源上的独占锁,不兼容,就导致了会话B被阻塞住了,那么会话B就进入到一个等待队列里。

会话C也需要访问相同的资源,由于需要修改数据,所以需要加上独占锁,但于会话A已加上的独占锁,不兼容,于是会话C也被阻塞住了,那么会话C也会进入到等待队列中,排在会话B之后。

会话C被阻塞的原因:

从上图可以看出,会话C在把Page  1  :21339上的IU锁改为IX锁时,没有grant,而是处于convert状态,之所要修改,是因为需要修改id为100000的数据。

而之前已经在1  :21339上加了IU锁,在RID 1:21339:1 上加了U锁,要修改这个这个页中的数据,必须要把IU锁修改为IX锁,如果成功,那么继续把U锁修改为X锁。

从上述分析中,可以看出SQL Server中的锁采用是队列的机制,即先进先出。

SQL Server 锁的排队机制

时间: 2024-10-08 10:05:45

SQL Server 锁的排队机制的相关文章

了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密

关系型数据库,如SQL Server,使用锁来避免多用户修改数据时的并发冲突.当一组数据被某个用户锁定时,除非第一个用户结束修改并释放锁,否则其他用户就无法修改该组数据. 有些数据库,包括SQL Server,用锁来避免用户检索未递交的修改记录.在这些系统中,如果用户A在修改一组记录,则其他用户只有等用户A修改完毕了,才能检索. 数据库在每个物理层上设置锁:记录行(rows),数据页(pages, 上百万记录行),扩展页(extends, 多个数据页),整个表,甚至整个数据库.有些数据库(如Or

SQL Server锁分区特性引发死锁解析

原文:SQL Server锁分区特性引发死锁解析 锁分区技术使得SQL Server可以更好地应对并发情形,但也有可能带来负面影响,这里通过实例为大家介绍,分析由于锁分区造成的死锁情形. 前段时间园友@JentleWang在我的博客锁分区提升并发,以及锁等待实例中问及锁分区的一些特性造成死锁的问题,这类死锁并不常见,我们在这里仔细分析下.不了解锁分区技术的朋友请先看下我的锁分区那篇实例. Code(执行测试脚本时请注意执行顺序,说明) 步骤1 创建测试数据 use tempdb go creat

Sql Server Tempdb原理-日志机制解析实践

笔者曾经在面试DBA时的一句”tempdb为什么比其他数据库快?”使得95%以上的应试者都一脸茫然.Tempdb作为Sqlserver的重要特征,一直以来大家对它可能即熟悉又陌生.熟悉是我们时时刻刻都在用,陌生可能是很少有人关注它的运行机制.这次我将通过实例给大家介绍下tempdb的日志机制. 测试用例 我们分别在用户数据库(testpage),tempdb中创建相似对象t1,#t1,并在tempdb中创建创建非临时表,然后执行相应的insert脚本(用以产生日志),并记录执行时间用以比较用以比

lock(1)——创建及更新表过程中SQL SERVER锁资源分配情况

锁应该说是由关系型数据库ACID(Atomicity,Consistency,Isolation,Durability)特性而引出的. 以下将测试在创建及更新表过程中SQL Server锁资源分配情况 获取当前会话的事务隔离级别:DBCC USEROPTIONS 测试环境:SQL SERVER 2008 R2 read committed隔离级别下 创建表 当我们只是打开一个SSMS查询窗口,选择数据库为master和tempdb时,没有任何锁产生,当我选择其他数据库,sql server就会在

Sql server锁机制

如何查看锁 了解SQL Server在某一时间点上的加锁情况无疑是学习锁和诊断数据库死锁和性能的有效手段.我们最常用的查看数据库锁的手段不外乎两种: 使用sys.dm_tran_locks这个DMV SQL Server提供了sys.dm_tran_locks这个DMV来查看当前数据库中的锁,前面的图2就是通过这个DMV来查看的. 这里值得注意的是sys.dm_tran_locks这个DMV看到的是在查询时间点的数据库锁的情况,并不包含任何历史锁的记录.可以理解为数据库在查询时间点加锁情况的快照

SQL Server 锁

锁是一种防止在某对象执行动作的一个进程与已在该对象上执行的其他进行相冲突的机制.也就是说,如果有其他人在操作某个对象,那么你旧不能在该对象上进行操作.你能否执行操作取决于其他用户正在进行的操作. 通过锁可以防止的问题 锁可以解决以下4种主要问题: 脏读 非重复性读取 幻读 丢失更新 1.脏读 如果一个事务读取的记录是另一个未完成事务的一部分,那么这时就发生了脏读.如果第一个事务正常完成,那么就有什么问题.但是,如果前一个事务回滚了呢,那将从数据库从未发生的事务中获取了信息. 2.非重复性读取 很

SQL Server 锁实验(SELECT加锁探究)

本例中使用begin tran和with (holdlock)提示来观察SQL Server在select语句中的锁. 开启事务是为了保证时间极短的查询也能观察到锁情况,因为holdlock会在事务结束后释放锁. 1. 查询主键索引的select语句 其上锁情况为: 这里我选择了一较为靠前的主键值,结果集有6条,因为是主键索引的范围扫描因此扫描到第7行时停止,所以持有7个KEY锁,此外这些记录都在一个页中(1:3104页),因此最终的情况就是上图所示的7个KEY锁和一个数据页的IS锁.这里每一个

SQL Server 锁实验(UPDATE加锁探究)

本例中使用begin tran和with (holdlock)提示来观察SQL Server在select语句中的锁. 开启事务是为了保证时间极短的查询也能观察到锁情况,因为holdlock会在事务结束后释放锁. update语句: 其上锁情况为: 可以看到加锁情况如下: 1.添加了表级IX锁 2.针对数据页3105添加了IX锁,以便更新其中数据行 3.对数据页3105中对应的数据行添加了X模式的KEY锁 4.更新完数据后要更新包含ClinicID列的相关索引,我们先看一下涉及到这个列的索引有哪

sql server锁检测

有时候系统运行老感觉效率不高,并且有时候sql还有超时的报错,但是并发量并不高.通过排查定位sql是否有执行效率问题 -- 开事务, 以保持锁 BEGIN TRAN -- 更新 update table a set column1 = 1 where idx = 1 -- 列出锁信息 EXEC sp_lock @@spid -- 提交或者回滚事务 COMMIT/ROLLBACK TRAN 通过执行sp_lock存储过程,查看锁信息(类似如下) spid dbid ObjId IndId Type