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

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

锁分区技术使得SQL Server可以更好地应对并发情形,但也有可能带来负面影响,这里通过实例为大家介绍,分析由于锁分区造成的死锁情形.

前段时间园友@JentleWang在我的博客锁分区提升并发,以及锁等待实例中问及锁分区的一些特性造成死锁的问题,这类死锁并不常见,我们在这里仔细分析下.不了解锁分区技术的朋友请先看下我的锁分区那篇实例.

Code(执行测试脚本时请注意执行顺序,说明)

步骤1 创建测试数据

use tempdb
go
create table testdlk
(
id int identity(1,1) primary key,
str1 char(3000)
)
go
insert into testdlk(str1) select 'aaa'
insert into testdlk(str1) select 'bbb'
insert into testdlk(str1) select 'ccc'
insert into testdlk(str1) select 'ddd'

步骤2 开启 session 1 执行语句

--session 1
begin tran 

update testdlk set str1='ttt' where id=1

---session id 55 this example
---rollback tran
---manual after session 3 rollback session 1

步骤3 开启session 2 执行语句

--session 2
BEGIN TRAN

update testdlk set str1='abc' where id=2 ---update the content of id=2

SELECT * FROM testdlk WITH(TABLOCKX)------ try to get X lock on the object testdlk

rollback tran
---session id 58 this example

步骤4 开启session 3执行数据

--session 3
BEGIN TRAN

update testdlk set str1='abc' where id=3-------update the content of id=3 

SELECT * FROM testdlk WITH(TABLOCKX)--- try to get X lock on the object testdlk

rollback tran
---session id 59 this example

步骤5 创建脚本的session中执行语句

select request_session_id,resource_lock_partition,resource_type,
object_name(resource_associated_entity_id) as object_name,request_mode,request_status
from sys.dm_tran_locks where resource_database_id=2 and resource_type='OBJECT'

select session_id,blocking_session_id,wait_type,resource_description
from sys.dm_os_waiting_tasks where blocking_session_id is not null

步骤6 session 1中rollback

Rollback session 1
--when session 1 rollback then session 3 deadlock

当session 1回滚时,session2 session 3造成死锁,session 3牺牲.

原因分析.

通过步骤四我们可以得到相应的会话的锁,及相关等待情况如图1-1

                                                                图1-1

 

可以看到session 1(图中55)由于只是更新id=1的列,所以它会在key上加排它锁(图中未列出,感兴趣朋友可以自行查看),而在Object testdlk中某个锁分区中图中为锁分区1加上意向排它锁.

Session 2(图中58)由于更新了id=2的列,所以会在相应Key上加排他锁,并在某个锁分区中加意向排他锁(IX),于此同时由于此事务下面查询有表级TABLOCKX Hint,此时58会尝试在表级上排他锁(X锁).由于X锁需要在所有锁分区中获得,此时58在锁分区0中获得X锁,但由于锁分区1中有55获得了意向排他锁(IX),所以58在锁分区1中尝试获取X锁时状态未Convert,被55阻塞.

Session 3(图中59)由于更新了id=3的列,所以会在相应key上加排他锁,同时在某个锁分区中加意向排他锁(IX),于此同时由于此事务下面查询同样有表级TABLOCKX Hint,这时59也会尝试在表的所有分区中获取X锁.由于58已经获得锁分区0的X锁,所以当59尝试获取锁分区0的X锁时,就会被58阻塞,状态为Wait.

问题来了,当55回滚时,其上面的锁也将被释放.此时58,59都试图获得表级的所有分区X锁,而又同时在锁分区中持有IX锁,这时死锁就不可避免了.

死锁视图如图1-2所示.

 

                                              图1-2

 

问题解决

经过分析,可以看出是由于锁分区的特性导致IX与不同spid中的X互斥导致,那如果能禁用锁分区特性不就没有在个别分区上的IX这回事儿了吗.这里介绍一个启动标记 trace flag 1229,可以禁用锁分区特性.我们可以通过配置管理器中添加启动标记,也可以在command启动时加上响应参数.应当注意当使用配置管理器时,我们应在启动参数末尾配置”-T1229”,如果使用command,这时是t1229(大小写区分)

这里我用win中command启用

Code

Net start mssqlserver /t1229

重新启动后重复上述实例,死锁就不在出现了.

注:此实例只为说明由于锁分区造成的死锁情形,实际生产中此类情形却是罕见的,除非遇到这类情形并且没有更好的规避方式,一般我们还是建议默认此特性.这对提升并发是很有帮助的.

关于锁分区特性.

通过微软的在线文档可以得知,只有当CPU的逻辑数大于等于16时,才会默认开启此特性,而授权又是按照CPU收费的.问题来了,当CPU小于16我如果想利用此特性是否可以呢?这个再给大家介绍一个启动跟踪标记 trace flag 1228.当有两个及以上逻辑CPU时就会启动锁分区特性.不过我们使用时清楚自己的使用场景,是否会因此TF得到好处.由于这是无官方文档记录的特性,使用应只针对特定需求,并应慎重.

结语:SQL Server或是其他数据库系统中任何一个特性的引入总会适应大多数场景,但也会伴随着特定场景的弊端出现,清楚其所带来的利弊并合理使用,使得SQL Server适应场景,我们也能适应SQL Server.

时间: 2024-05-18 09:34:09

SQL Server锁分区特性引发死锁解析的相关文章

SQL Server 隐式转换引发的躺枪死锁-程序员需知

原文:SQL Server 隐式转换引发的躺枪死锁-程序员需知 在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍由于隐式数据类型转换而造成的死锁及相应解决方案. 现实中有些程序员/数据库开发者会根据数据库的处理机制实现一些应用,如抢座应用,可能会对事务中的查询加一些列的Hint以细化粒度,实现应用的同时使得影响最低,但也有可能因为一些小细节的欠缺

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

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

谈谈我的微软特约稿:《SQL Server 2014 新特性:IO资源调控》

原文:谈谈我的微软特约稿:<SQL Server 2014 新特性:IO资源调控> 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 篡写经历(Experience) 特约稿正文(Content-body) 第一部分:生活中资源调控器: 第二部分:SQL Server中资源调控器: 第三部分:SQL Server资源调控器运用场景-CPU: 第四部分:SQL Server资源调控器运用场景-IO: 第五部分:总结: 第六部分:作者简介:

SQL Server -&gt;&gt; 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表)

原文:SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表) 作为SQL Server 2016(CTP3.x)的另一个新特性,Temporal Table(历史表)记录了表历史上任何时间点所有的数据改动.Temporal Table其实早在ANSI SQL 2011就提出了,而SAP HANA, DB2和Oracle早已在它们的产品中加入/实现了这一特性.所以说微软其实是落后了几个竞争对手.既然在CTP3.0中加入了,相信

SQL Server已分区索引的特殊指导原则(3)

一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的交流. SQL Server 解读[已分区索引的特殊指导原则](1)- 索引对齐 SQL Server 解读[已分区索引的特殊指导原则](2)- 唯一索引分区 二.解读 [对非聚集索引进行分区] "对唯一的非聚集索引进行分区时,索引键必须包含分区依据列.对非唯一的非聚集索引进行分区时,默认情况下 S

SQL Server已分区索引的特殊指导原则(2)- 唯一索引分区

一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的交流. 二.解读 [对唯一索引进行分区] "对唯一索引(聚集或非聚集)进行分区时,必须从唯一索引键使用的分区依据列中选择分区依据列.此限制将使 SQL Server 只调查单个分区,以确保表中不存在重复的新键值.如果分区依据列不可能包含在唯一键中,则必须使用 DML 触发器,而不是强制实现唯一性.&

小心SQL SERVER 2014新特性——基数评估引起一些性能问题

  在前阵子写的一篇博文"SQL SERVER 2014 下IF EXITS 居然引起执行计划变更的案例分享" 里介绍了数据库从SQL SERVER 2005升级到 SQL SERVER 2014后,发现一个SQL出现性能问题,当时分析后发现执行计划变了,导致SQL出现了性能问题.但是没有彻底搞清楚为什么出现这种情况.当时看到 Actual Number of Rows 与Estimated Number of Rows之间的偏差较大(统计信息是最新的),以为是优化器的Bug造成的.其

小心SQL SERVER 2014新特性&amp;mdash;&amp;mdash;基数评估引起一些性能问题

    在前阵子写的一篇博文"SQL SERVER 2014 下IF EXITS 居然引起执行计划变更的案例分享"里介绍了数据库从SQL SERVER 2005升级到 SQL SERVER 2014后,发现一个SQL出现性能问题,当时分析后发现执行计划变了,导致SQL出现了性能问题.但是没有彻底搞清楚为什么出现这种情况.当时看到Actual Number of Rows 与Estimated Number of Rows之间的偏差较大(统计信息是最新的),以为是优化器的Bug造成的.其

SQL Server优化器特性-隐式谓词

原文:SQL Server优化器特性-隐式谓词 我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性-隐式谓词,并简单介绍在此特性下如何根据场景控制优化器的行为.    在这里我通过一个简单的实例来给大家说明下. code CREATE TABLE T1 (A INT, B INT) CREATE TABLE T2 (A INT, B INT) set