一次简单的死锁分析

数据库错误日志中监测到如下死锁:

deadlock-list
 deadlock victim=process16fc9dd498
  process-list
   process id=process16fc9dd498 taskpriority=0 logused=0 waitresource=KEY: 7:72057595333771264 (58bb110a434d) waittime=2239 ownerId=8413250494 transactionname=user_transaction lasttranstarted=2016-07-01T22:52:34.180 XDES=0x892f80d28 lockMode=U schedulerid=81 kpid=10732 status=suspended spid=242 sbid=0 ecid=0 priority=0 trancount=3 lastbatchstarted=2016-07-01T22:52:34.183 lastbatchcompleted=2016-07-01T22:52:34.180 lastattention=1900-01-01T00:00:00.180 clientapp=pytds hostname=adj52 hostpid=31708 loginname=app_rw isolationlevel=read committed (2) xactid=8413250494 currentdb=7 lockTimeout=4294967295 clientoption1=671219744 clientoption2=128056
    executionStack
     frame procname=xxx.dbo.gsp_InsertCustomerInfo_v2 line=32 stmtstart=2358 stmtend=2582 sqlhandle=0x030007004577437e8a39af005ba5000001000000000000000000000000000000000000000000000000000000
update D_CustomerInfo set CustomerName[email protected], [email protected] where cellPhone=@CellPhone
     frame procname=adhoc line=1 stmtstart=316 sqlhandle=0x010007008d0ab52e709f6cd40100000000000000000000000000000000000000000000000000000000000000
exec gsp_InsertCustomerInfo_v2
     frame procname=unknown line=1 sqlhandle=0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
unknown
    inputbuf
   exec gsp_InsertCustomerInfo_v2
   process id=process16fd5b1868 taskpriority=0 logused=40140 waitresource=KEY: 7:72057595738193920 (8111eec6ede3) waittime=2224 ownerId=8411580132 transactionname=user_transaction lasttranstarted=2016-07-01T22:40:56.053 XDES=0x5405ce3a8 lockMode=U schedulerid=52 kpid=9136 status=suspended spid=339 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2016-07-01T22:52:34.180 lastbatchcompleted=2016-07-01T22:40:56.053 lastattention=2016-07-01T22:40:56.053 clientapp=pytds hostname=adj52 hostpid=33727 loginname=app_rw isolationlevel=read committed (2) xactid=8411580132 currentdb=7 lockTimeout=5000 clientoption1=671219744 clientoption2=128056
    executionStack
     frame procname=xxx.dbo.zxf_InsertOrder_v9 line=1109 stmtstart=62672 stmtend=62860 sqlhandle=0x030007009ab5d3576d78a30036a6000001000000000000000000000000000000000000000000000000000000
UPDATE D_CustomerInfo set isFree = 2,isbaidu=1  where Cellphone = @CellPhone
    --更新司机状态
     frame procname=adhoc line=1 stmtstart=2308 sqlhandle=0x01000700bdbd0606b05ecde93100000000000000000000000000000000000000000000000000000000000000
exec zxf_InsertOrder_v9
     frame procname=unknown line=1 sqlhandle=0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
unknown
    inputbuf
(@CellPhone VARCHAR(MAX),@FromCellPhone VARCHAR(MAX)....
  resource-list
   keylock hobtid=72057595333771264 dbid=7 objectname=xxx.dbo.D_CustomerInfo indexname=PK_D_CustomerInfo id=lock124ed8ee00 mode=X associatedObjectId=72057595333771264
    owner-list
     owner id=process16fd5b1868 mode=X
    waiter-list
     waiter id=process16fc9dd498 mode=U requestType=wait
   keylock hobtid=72057595738193920 dbid=7 objectname=aidaijiaNew.dbo.D_CustomerInfo indexname=idx_Cellphone__CustomerId_CustomerName_RecommendCode_Amount id=lock7bc3b8380 mode=U associatedObjectId=72057595738193920
    owner-list
     owner id=process16fc9dd498 mode=U
    waiter-list
     waiter id=process16fd5b1868 mode=U requestType=wait

process16fc9dd498

xxx.dbo.xxx_InsertCustomerInfo_v2

的语句:update D_CustomerInfo set [email protected], [email protected] where [email protected]

持有索引idx_Cellphone__xxxx页上7:72057595738193920 (8111eec6ede3)数据行的更新锁,等待获取主键PK_D_CustomerInfo上7:72057595333771264 (58bb110a434d)数据行的更新锁

process16fd5b1868

xxx.dbo.xxx_InsertOrder_v9

的语句:UPDATE D_CustomerInfo set isFree = 2,isbaidu=1  where Cellphone = @CellPhone

持有主键PK_D_CustomerInfo上7:72057595333771264 (58bb110a434d)数据行的排他锁,等待获取索引idx_Cellphone__xxxx页上7:72057595738193920 (8111eec6ede3)数据行的更新锁

最终process16fc9dd498成为了牺牲品。

--------------------------------------------------------

主键PK_D_CustomerInfo上锁定的内容可以这样查到:

SELECT %%lockres%% AS keyhashvalue,cellphone FROM  D_CustomerInfo
where
%%lockres%% = ‘(58bb110a434d)‘

那么索引idx_Cellphone__xxxx上锁定的内容7:72057595738193920 (8111eec6ede3)是不是也是同一个电话号码呢?我们可以试着从索引根节点往下找找看cellphone为13917XX6177的索引页上keyhashvalue是不是8111eec6ede3
首先找到索引的根节点:

Select dbo.f_get_page(I.root_page) root_page
FROM sys.partitions P
INNER JOIN SYS.allocation_units A
ON P.partition_id = A.container_id
INNER JOIN SYS.system_internals_allocation_units I
ON A.allocation_unit_id = I.allocation_unit_id
WHERE P.object_id = OBJECT_ID(‘D_CustomerInfo‘)
AND P.index_id = 66

再看看根节点的内容:

再找13916XXXX的ChildPage8503545

....

再找到ChildPage8506395,证实索引页上被锁定的也是同一个电话号码13917XX6177(KeyHashValue为8111eec6ede3)

-----------------------------------

死锁的形成过程:

1.xxx_InsertOrder_v9存储过程上开启了事务,并且先更新了一次D_CustomerInfo,但此更新不涉及idx_Cellphone__xxxx上的内容更新,因此仅持有了主键上13917XX6177这一行的排他锁。

2.xxx_InsertCustomerInfo_v2存储过程请求更新D_CustomerInfo,查询条件为cellphone,因此先获取了idx_Cellphone__xxxx上13917XX6177这一行的更新锁,之后申请主键上13917XX6177这一行更新锁时被迫等待xxx_InsertOrder_v9释放排他锁。

3.xxx_InsertOrder_v9执行到后面再次需要更新D_CustomerInfo,更新查询条件为cellphone,因此申请获取idx_Cellphone__xxxx上13917XX6177这一行的更新锁,但由于更新锁被xxx_InsertCustomerInfo_v2给占有了,被迫等待。

因此互相构成了死锁,xxx_InsertCustomerInfo_v2成为了牺牲品。

----------------------------------

死锁的解决方案:

解决方案1.xxx_InsertOrder_v9中两次更新D_CustomerInfo改为集中到一次更新

解决方案2.xxx_InsertOrder_v9中在判断客户是否存在时可以直接select *** from D_CustomerInfo with(updlock,rowlock) where cellphone = XXXX,那么之后的update 也不会释放idx_Cellphone__xxxx上的更新锁,当然这会使锁定资源变多,时间变长。

时间: 2024-09-29 21:03:55

一次简单的死锁分析的相关文章

一个最不可思议的MySQL死锁分析

一个最不可思议的MySQL死锁分析 死锁问题背景 做MySQL代码的深入分析也有些年头了,再加上自己10年左右的数据库内核研发经验,自认为对于MySQL/InnoDB的加锁实现了如指掌,正因如此,前段时间,还专门写了一篇洋洋洒洒的文章,专门分析MySQL的加锁实现细节:<MySQL加锁处理分析>. 但是,昨天"润洁"同学在<MySQL加锁处理分析>这篇博文下咨询的一个MySQL的死锁场景,还是彻底把我给难住了.此死锁,完全违背了本人原有的锁知识体系,让我百思不得

Hadoop初学指南(6)--MapReduce的简单实例及分析

本文在上一节的基础上通过一个简单的MR示例对MapReduce的运行流程进行分析. 假设有两行数据,分别是hello you,hello me,我们要统计其中出现的单词以及每个单词出现的次数. 所得的结果为 hello   2 you     1 me      1 (1)大致运行流畅 1.解析成2个<k,v>,分别是<0, hello you><10, hello me>.调用2次map函数. 2.执行map任务 3.map输出后的数据是:<hello,1>

Java一个简单的死锁例子

内容:一个简单的死锁例子,大概的思路:两个线程A和B,两把锁X和Y,现在A先拿到锁X,然后sleep()一段时间,我们知道sleep()是不会释放锁资源的.然后如果这段时间线程B拿到锁Y,也sleep()一段时间的话,那么等到两个线程都醒过来的话,那么将互相等待对方释放锁资源而僵持下去,陷入死锁.flag的作用就是让A和B获得不同的锁. public class TestDeadLock { public void run() { MyThread mt = new MyThread(); ne

Androidpn 简单实现及分析

(文中部分内容来自网络) XMPP协议: XMPP : The Extensible Messaging andPresence Protocol. 中文全称:可扩展通讯和表示协议. 简介:可扩展通讯和表示协议 (XMPP) 可用于服务类实时通讯.表示和需求响应服务中的XML数据元流式传输. XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测. 它在促进服务器之间的准即时操作.这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息

《人民的名义》---简单的文本分析

我们都知道进行自然语言处理的第一步就是分词,下面使用jieba模块对最近比较热的电视剧<人民的名义>进行分词,并对它进行一些简单的文本分析. 一.jieba模块中常用的方法说明(github): 1.分词: jieba.cut 方法接受三个输入参数: 需要分词的字符串:cut_all 参数用来控制是否采用全模式:HMM 参数用来控制是否使用 HMM 模型 jieba.cut_for_search 方法接受两个参数:需要分词的字符串:是否使用 HMM 模型.该方法适合用于搜索引擎构建倒排索引的分

Greenplum 简单性能测试与分析

如今,多样的交易模式以及大众消费观念的改变使得数据库应用领域不断扩大,现代的大型分布式应用系统的数据膨胀也对数据库的海量数据处理能力和并行处理能力提出了更高的要求,如何在数据呈现海量扩张的同时提高处理速度和应用系统的可用性,使客户能同时得到更高的处理速度.更高的数据可用性和更大的数据集,是数据库系统面临的一个挑战. 通过TPC-H基准测试,可获得数据库单位时间内的性能处理能力,为评估数据库系统的现有性能服务水平提供有效依据,通过横向对比促进数据库系统的整体质量提升,能更好地在重大信息化工程中实现

java实现简单web服务器(分析+源代码)

在日常的开发中,我们用过很多开源的web服务器,例如tomcat.apache等等.现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器.为了简化操作,这里不考虑资源不存在等异常情况.web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键.先看下一般的HTTP请求和响应报文的一般格式: HTTP 请求报文 HTTP 响应报文 web服务器获取一个用户的连接时,会初始化一个线程和用户通信,代码如下:

javascript简单计算器代码分析

javascript简单计算器代码分析:也许网页中需要一个简单的计算器功能,这个时候就要掌握如何编写,起码应该会修改,下面就通过一个简单的实例介绍一下如何实现简单的计算器效果,代码实例如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/&

linux下简单抓包分析

有时候会遇到一些问题需要我们来抓包分析,当手头又没有专业的抓包工具的时候,可以用tcpdump来替代一下(一般的发行版都自带这个工具) 比如我们要分析一下eth0接口下跟192.168.7.188 这个目的IP地址22端口的发包情况 tcpdump -i eth0 dst 192.168.7.188 and port 22 tcpdump -i eth0 dst 192.168.7.188 and port 22 tcpdump: verbose output suppressed, use -