SQL Server 隐式转换引发的死锁
在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍由于隐式数据类型转换而造成的死锁及相应解决方案.
现实中有些程序员/数据库开发者会根据数据库的处理机制实现一些应用,如抢座应用,可能会对事务中的查询加一些列的Hint以细化粒度,实现应用的同时使得影响最低,但也有可能因为一些小细节的欠缺而引发错误,从而造成糟糕的用户体验.如下面这个例子
生成测试数据
code
01.create table testlock02.(ID varchar(10) primary key clustered,03.col1 varchar(20),04.col2 char(200))05.go----------create test table06. 07.declare @i int08.set @i = 109.while @i < 10010.begin11.insert into testlock12.select right(replicate('0',10)+ cast(@i as varchar(10)),10),'aaa','fixchar'13.set @i = @i+114.end15.go----------generate test data此时我们打开trace profiler 跟踪死锁相关信息
然后分别在两个session中运行如下语句
code
01.declare @ID nvarchar(10)02. 03.begin tran 04. 05.select top 1 @ID = ID from testlock with(updlock, rowlock, readpast)06.where col1 = 'aaa'07.order by id asc08. 09.select @ID10. 11.waitfor delay '00:00:20'12. 13.update testlock set col1 = 'bbb' where id = @ID14. 15.commit tran大约20s后我们可以从trace 中捕捉到死锁了如图1-1

问题分析
从死锁图中看既然更新既然拥有了自己的键锁为何要其它会话的呢?很明显,可能期望的锁粒度扩大了.
进而分析任意一个会话的执行计划语句发现了异常,最后的更新出现了隐式数据类型转换,以至于做了额外的聚集表扫描过程,致使执行更新过程需要所有键的U锁,从而引发了死锁.
如图1-2

为什么会出现隐式转换呢,通过检查执行的代码发现"declare @ID nvarchar(10)"
而表testlock中ID的定义是varchar(10) 问题就出在这里.
这里介绍一个小的知识点:数据类型优先级
当运算符表达式中数据类型不同时,按照类型的优先级低优先级的向高优先级的数据类型转换.当然如果两个数据类型不支持隐式转换则失败报错.
通过数据类型优先级列表发现nvarchar是高于varchar的,所以varchar将向nvarchar转换,进而使优化器选择了意料之外的执行计划,从而引发了死锁
如图1-3

详细参考
https://msdn.microsoft.com/zh-cn/library/ms190309.aspx
解决
找到问题的根源了,解决起来也就简单了,我们只需将查询中定义的declare @ID nvarchar(10)
调整为varchar即可(甚至char,通过优先级列表可知,char低于varchar.)
code
01.declare @ID varchar(10)02. 03.begin tran 04. 05.select top 1 @ID = ID from testlock with(updlock, rowlock, readpast)06.where col1 = 'aaa'07.order by id asc08. 09.select @ID10. 11.waitfor delay '00:00:20'12. 13.update testlock set col1 = 'bbb' where id = @ID14. 15.commit tran我们可以看到相应的执行计划发生了改变,我们期待的执行计划出现了.如图1-4

至此,问题解决.
注意:虽然有数据优先级,但建议大家在做开发时,定义的变量要与目标表的数据类型一致,从根源上避免隐式转换.
结语:一个小小的字符当真是可以引发血案,在做应用开发中我们需要知道每个字符的深刻含义.
SQL Server 隐式转换引发的死锁的更多相关文章
- SQL Server 隐式转换引发的躺枪死锁-程序员需知
在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍 ...
- SQL SERVER中隐式转换的一些细节浅析
其实这是一篇没有技术含量的文章,精通SQL优化的请绕道.这个缘起于在优化一个SQL过程中,同事问了我一个问题,为什么SQL中存在隐式转换,但是执行计划没有变? 我思索了一下,觉得这个问题也有点意思,说 ...
- SQL Server中提前找到隐式转换提升性能的办法
http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...
- 【转】SQL SERVER标量表达式的隐式转换
在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以 ...
- SQL Server有意思的数据类型隐式转换问题
写这篇文章的时候,还真不知道如何取名,也不知道这个该如何将其归类.这个是同事遇到的一个案例,案例比较复杂,这里抽丝剥茧,仅仅构造一个简单的案例来展现一下这个问题.我们先构造测试数据,如下所示: CRE ...
- SQL Server ->> 数据类型不一致比较时的隐式转换
当使用操作符进行比较的时候,两边数据类型不一致的情况下,数据类型优先级别低的会往优先级别高的发生隐式转换.下面的参考链接是优先级别列表. 参考: Data Type Precedence (Trans ...
- 数栈SQL优化案例:隐式转换
MySQL是当下最流行的关系型数据库之一,互联网高速发展的今天,MySQL数据库在电商.金融等诸多行业的生产系统中被广泛使用. 在实际的开发运维过程中,想必大家也常常会碰到慢SQL的困扰.一条性能不好 ...
- MySQL SQL优化之字符串索引隐式转换
之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结 ...
- C++ 构造函数 隐式转换 深度探索,由‘类对象的赋值操作是否有可能调用到构造函数’该实验现象引发
Test1 /** Ques: 类对象的赋值操作是否有可能调用到构造函数 ? **/ class mystring { char str[100]; public: mystring() //myst ...
随机推荐
- win10 IIS 10.0 无法安装 URL Rewrite Module 重写模块
打开注册表 win+R 输入 regidit在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp位置 修改注册表 把MajorVersion的值改为9 安装 ...
- 解决linux下root运行Elasticsearch异常
如果以root身份运行将会出现以下问题 root@yxjay:/opt/elasticsearch-2.3.5/bin# ./elasticsearchException in thread &quo ...
- Java多线程-线程的生命周期
线程可以分为4个状态:New(新生),Runnable(可运行):为了方便分析,还可将其分为:Runnable与Running.blocked(被阻塞),Dead(死亡). 与人有生老病死一样,线程也 ...
- 使用net.sf.fjep.fatjar插件将第三方JAR包打包进自已的JAR包中
一般单个工程,在没有应用别人的jar包时导出为jar很简单,只要设置一个Main-Class就行了,也就是选择程序入口(main所在类).但是涉及到了数据库或需要用到第三方的JAR,就需要用到相应的数 ...
- 实现二叉树的基本操作(Java版)
近期研究了一下二叉树,试着用Java语言实现了二叉树的基本操作,下面分享一下实现代码: package com.sf.test; import java.util.ArrayDeque; import ...
- CyclicBarrier的使用
最近一直整并发这块东西,顺便写点Java并发的例子,给大家做个分享,也强化下自己记忆,如果有什么错误或者不当的地方,欢迎大家斧正. CyclicBarrier是一种多线程并发控制实用工具,和Count ...
- 字符串匹配——C++使用Regex
需要#include < regex > 匹配 regex_match ("subject", std::regex("(sub)(.*)") ...
- 为什么要用Android Studio?
为什么要用Android Studio 本书节选自<Android Studio实用指南> 作者: 毕小朋 目前本书已上传到百度阅读,在百度中搜索[Anroid Studio实用指南]便可 ...
- ubuntu tensorflow cpu Faster-RCNN配置参考
https://blog.csdn.net/qq_36652619/article/details/85006559 (参考) https://blog.csdn.net/zcy0xy/art ...
- eclipse 使用 scons 编译的配置说明
eclipse版本: eclipse-cpp-kepler-SR1-win32.zip 创建项目必须选择“Makefile Project” 然后进入“Projects Properities” 先 ...