在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍由于隐式数据类型转换而造成的死锁及相应解决方案.

现实中有些程序员/数据库开发者会根据数据库的处理机制实现一些应用,如抢座应用,可能会对事务中的查询加一些列的Hint以细化粒度,实现应用的同时使得影响最低,但也有可能因为一些小细节的欠缺而引发错误,从而造成糟糕的用户体验.如下面这个例子

生成测试数据

code

01.create table testlock
02.(ID varchar(10) primary key clustered,
03.col1 varchar(20),
04.col2 char(200))
05.go----------create test table
06. 
07.declare @i int
08.set @i = 1
09.while @i < 100
10.begin
11.insert into testlock
12.select right(replicate('0',10)+ cast(@i as varchar(10)),10),'aaa','fixchar'
13.set @i = @i+1
14.end
15.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 asc
08. 
09.select  @ID
10. 
11.waitfor delay '00:00:20'
12. 
13.update testlock set col1 = 'bbb' where id = @ID
14. 
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 asc
08. 
09.select  @ID
10. 
11.waitfor delay '00:00:20'
12. 
13.update testlock set col1 = 'bbb' where id = @ID
14. 
15.commit tran

我们可以看到相应的执行计划发生了改变,我们期待的执行计划出现了.如图1-4

至此,问题解决.

注意:虽然有数据优先级,但建议大家在做开发时,定义的变量要与目标表的数据类型一致,从根源上避免隐式转换.

结语:一个小小的字符当真是可以引发血案,在做应用开发中我们需要知道每个字符的深刻含义.

SQL Server 隐式转换引发的死锁的更多相关文章

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

    在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍 ...

  2. SQL SERVER中隐式转换的一些细节浅析

    其实这是一篇没有技术含量的文章,精通SQL优化的请绕道.这个缘起于在优化一个SQL过程中,同事问了我一个问题,为什么SQL中存在隐式转换,但是执行计划没有变? 我思索了一下,觉得这个问题也有点意思,说 ...

  3. SQL Server中提前找到隐式转换提升性能的办法

        http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...

  4. 【转】SQL SERVER标量表达式的隐式转换

    在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以 ...

  5. SQL Server有意思的数据类型隐式转换问题

    写这篇文章的时候,还真不知道如何取名,也不知道这个该如何将其归类.这个是同事遇到的一个案例,案例比较复杂,这里抽丝剥茧,仅仅构造一个简单的案例来展现一下这个问题.我们先构造测试数据,如下所示: CRE ...

  6. SQL Server ->> 数据类型不一致比较时的隐式转换

    当使用操作符进行比较的时候,两边数据类型不一致的情况下,数据类型优先级别低的会往优先级别高的发生隐式转换.下面的参考链接是优先级别列表. 参考: Data Type Precedence (Trans ...

  7. 数栈SQL优化案例:隐式转换

    MySQL是当下最流行的关系型数据库之一,互联网高速发展的今天,MySQL数据库在电商.金融等诸多行业的生产系统中被广泛使用. 在实际的开发运维过程中,想必大家也常常会碰到慢SQL的困扰.一条性能不好 ...

  8. MySQL SQL优化之字符串索引隐式转换

    之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结 ...

  9. C++ 构造函数 隐式转换 深度探索,由‘类对象的赋值操作是否有可能调用到构造函数’该实验现象引发

    Test1 /** Ques: 类对象的赋值操作是否有可能调用到构造函数 ? **/ class mystring { char str[100]; public: mystring() //myst ...

随机推荐

  1. WPF 绑定以基础数据类型为集合的无字段名的数据源

    WPF 绑定以基础数据类型为集合的无字段名的数据源 运行环境:Window7 64bit,.NetFramework4.61,C# 6.0: 编者:乌龙哈里 2017-02-21 我们在控件的数据绑定 ...

  2. 导入本体到Jena TDB数据库

    本体的存储方法或称本体持久化,大致分为基于内存的方式.基于文件的方式.基于数据库的方式和专门的管理工具方式4种(傅柱等, 2013).其中,基于数据库的方式又有基于关系数据库.基于面向对象数据库.基于 ...

  3. Solr集群—SolrCloud

    1.   学习计划 1.solr集群搭建 2.使用solrj管理solr集群 3.把搜索功能切换到集群版 2.   什么是SolrCloud SolrCloud(solr 云)是Solr提供的分布式搜 ...

  4. Unity牛逼的2D纹理功能

    [Unity牛逼的2D纹理功能] 1.可直接将贴图生成成为Cubemap. 2.自动生成Mipmap. 3.查看纹理被当前场景哪些对象引用.在Project窗口中,右击图像,选择 参考:file:// ...

  5. preview放大镜

    [preview放大镜] preview有放大镜功能,放`键即可(键盘左上角,1左边的键).

  6. 【BZOJ2038】小Z的袜子【莫队】

    题意 给出包含n个数字的序列,和m个查询.每次查询问区间[l,r]中挑选出两个数字,大小相同的概率为多少. 分析 莫队的入门题吧.代码是非常好写,关键是时间复杂度的证明.O(n*sqrt(n)).我还 ...

  7. iOS无网络提示或无数据提示空白页

    在我们平常我们用的app当中,当你在信号不好网络错误的时候,一般都会有个提示:“网络错误请点击重试~” 的话术,或者说当你浏览某一页的时候,没有数据,也会提示:“暂无数据,请搞点动静” 之类的话术. ...

  8. 快速上手Runtime(一)之消息机制

    Runtime简介 Runtime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于动态 ...

  9. 微信小程序开发教程,大多数人都搞错的八个问题

    小程序目前被炒得沸沸扬扬,无数媒体和企业借机获取阅读流量. 这再次证明一点,微信想让什么火,真的就能让什么火.这种能力真是全中国再也没有人有了,政府也没有. 但四处传的消息很多是失真的,废话不说,先列 ...

  10. 637. Average of Levels in Binary Tree 二叉树的层次遍历再求均值

    [抄题]: Given a non-empty binary tree, return the average value of the nodes on each level in the form ...