记录一次高并发下由索引引发的死锁问题

先上一个存储过程

CREATE PROCEDURE [dbo].[GetNextIncrease]
@key varchar(50),
@next int output
as
begin
    begin try
         begin tran
            select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key]=@key;
            --if @next!=NULL
                begin
                    update cfg_increase set NextVal=(NextVal+1) WHERE [Key]=@key;
                end
            --else
            --    begin
            --        update btlh_dep_hdbh set hd=1 WHERE [email protected];
            --    end
         commit
    end try
    begin catch
        rollback
    end catch
end
GO

根据存储过程生成一个流水号。

表结构:

CREATE TABLE [dbo].[cfg_increase](
    [Id] [INT] IDENTITY(1,1) NOT NULL,
    [Key] [NVARCHAR](255) NOT NULL,
    [NextVal] [INT] NOT NULL,
 CONSTRAINT [PK__cfg_incr__3214EC07351DDF8C] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

EXEC sys.sp_addextendedproperty @name=N‘MS_Description‘, @value=N‘自增序列标识‘ , @level0type=N‘SCHEMA‘,@level0name=N‘dbo‘, @level1type=N‘TABLE‘,@level1name=N‘cfg_increase‘, @level2type=N‘COLUMN‘,@level2name=N‘Key‘
GO

EXEC sys.sp_addextendedproperty @name=N‘MS_Description‘, @value=N‘自增序列下一个值‘ , @level0type=N‘SCHEMA‘,@level0name=N‘dbo‘, @level1type=N‘TABLE‘,@level1name=N‘cfg_increase‘, @level2type=N‘COLUMN‘,@level2name=N‘NextVal‘
GO

EXEC sys.sp_addextendedproperty @name=N‘MS_Description‘, @value=N‘自定义键自增序列‘ , @level0type=N‘SCHEMA‘,@level0name=N‘dbo‘, @level1type=N‘TABLE‘,@level1name=N‘cfg_increase‘
GO

key列上无索引, 脚本根据key 更新表的nextValue。

在高并发下抓取到的一个死锁

<deadlock-list>
 <deadlock victim="process20ec00bc8">
  <process-list>
   <process id="process20ec00bc8" taskpriority="0" logused="16928" waitresource="KEY: 9:72057594111787008 (8194443284a0)" waittime="6494" ownerId="2653399770"
   transactionname="user_transaction" lasttranstarted="2019-07-22T15:41:26.487" XDES="0xb0ec9790" lockMode="U" schedulerid="8" kpid="0"
   status="suspended" spid="99" sbid="0" ecid="0" priority="0" trancount="3" lastbatchstarted="2019-07-22T15:41:26.500"
   lastbatchcompleted="2019-07-22T15:41:26.500" clientapp=".Net SqlClient Data Provider" hostname="iZ5nf507j3o23hZ" hostpid="39352"
   loginname="sa" isolationlevel="read committed (2)" xactid="2653399770" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="tengda2019718.dbo.GetNextIncrease" line="11" stmtstart="474" stmtend="606" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
update cfg_increase set NextVal=(NextVal+1) WHERE [Key][email protected];     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 9 Object Id = 1201439354]    </inputbuf>
   </process>
   <process id="process9412988" taskpriority="0" logused="21428" waitresource="KEY: 9:72057594111787008 (a0c936a3c965)" waittime="6502" ownerId="2653399772"
   transactionname="user_transaction" lasttranstarted="2019-07-22T15:41:26.487" XDES="0xe7e45620" lockMode="X" schedulerid="6" kpid="0"
   status="suspended" spid="83" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2019-07-22T15:41:26.500"
   lastbatchcompleted="2019-07-22T15:41:26.500" clientapp=".Net SqlClient Data Provider" hostname="iZ5nf507j3o23hZ" hostpid="39352"
   loginname="sa" isolationlevel="read committed (2)" xactid="2653399772" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="tengda2019718.dbo.GetNextIncrease" line="8" stmtstart="242" stmtend="448" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key][email protected];
            --if @next!=NULL     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 9 Object Id = 1201439354]    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057594111787008" dbid="9" objectname="tengda2019718.dbo.cfg_increase" indexname="PK__cfg_incr__3214EC07351DDF8C" id="lock10fc9ea00" mode="X" associatedObjectId="72057594111787008">
    <owner-list>
     <owner id="process9412988" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process20ec00bc8" mode="U" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594111787008" dbid="9" objectname="tengda2019718.dbo.cfg_increase" indexname="PK__cfg_incr__3214EC07351DDF8C" id="lock12e75a280" mode="X" associatedObjectId="72057594111787008">
    <owner-list>
     <owner id="process20ec00bc8" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process9412988" mode="X" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>
 </deadlock>
</deadlock-list>

抓取到的另外一个死锁:

<deadlock-list>
 <deadlock victim="processba954c8">
  <process-list>
   <process id="processba954c8" taskpriority="0" logused="16384" waitresource="KEY: 9:72057594111787008 (8194443284a0)" waittime="1495" ownerId="2653399801" transactionname="user_transaction" lasttranstarted="2019-07-22T15:41:26.490" XDES="0x30e6833c0" lockMode="X" schedulerid="11" kpid="0" status="suspended" spid="91" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2019-07-22T15:41:26.507" lastbatchcompleted="2019-07-22T15:41:26.507" clientapp=".Net SqlClient Data Provider" hostname="iZ5nf507j3o23hZ" hostpid="39352" loginname="sa" isolationlevel="read committed (2)" xactid="2653399801" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="tengda2019718.dbo.GetNextIncrease" line="8" stmtstart="242" stmtend="448" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key][email protected];
            --if @next!=NULL     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 9 Object Id = 1201439354]    </inputbuf>
   </process>
   <process id="process20ec00bc8" taskpriority="0" logused="16928" waitresource="KEY: 9:72057594111787008 (8194443284a0)" waittime="1493" ownerId="2653399770" transactionname="user_transaction" lasttranstarted="2019-07-22T15:41:26.487" XDES="0xb0ec9790" lockMode="U" schedulerid="8" kpid="0" status="suspended" spid="99" sbid="0" ecid="0" priority="0" trancount="3" lastbatchstarted="2019-07-22T15:41:26.500" lastbatchcompleted="2019-07-22T15:41:26.500" clientapp=".Net SqlClient Data Provider" hostname="iZ5nf507j3o23hZ" hostpid="39352" loginname="sa" isolationlevel="read committed (2)" xactid="2653399770" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="tengda2019718.dbo.GetNextIncrease" line="11" stmtstart="474" stmtend="606" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
update cfg_increase set NextVal=(NextVal+1) WHERE [Key][email protected];     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 9 Object Id = 1201439354]    </inputbuf>
   </process>
   <process id="process9412988" taskpriority="0" logused="21428" waitresource="KEY: 9:72057594111787008 (a0c936a3c965)" waittime="1501" ownerId="2653399772" transactionname="user_transaction" lasttranstarted="2019-07-22T15:41:26.487" XDES="0xe7e45620" lockMode="X" schedulerid="6" kpid="0" status="suspended" spid="83" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2019-07-22T15:41:26.500" lastbatchcompleted="2019-07-22T15:41:26.500" clientapp=".Net SqlClient Data Provider" hostname="iZ5nf507j3o23hZ" hostpid="39352" loginname="sa" isolationlevel="read committed (2)" xactid="2653399772" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="tengda2019718.dbo.GetNextIncrease" line="8" stmtstart="242" stmtend="448" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key][email protected];
            --if @next!=NULL     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 9 Object Id = 1201439354]    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057594111787008" dbid="9" objectname="tengda2019718.dbo.cfg_increase" indexname="PK__cfg_incr__3214EC07351DDF8C" id="lock10fc9ea00" mode="X" associatedObjectId="72057594111787008">
    <owner-list>
     <owner id="process9412988" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="processba954c8" mode="X" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594111787008" dbid="9" objectname="tengda2019718.dbo.cfg_increase" indexname="PK__cfg_incr__3214EC07351DDF8C" id="lock10fc9ea00" mode="X" associatedObjectId="72057594111787008">
    <owner-list/>
    <waiter-list>
     <waiter id="process20ec00bc8" mode="U" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594111787008" dbid="9" objectname="tengda2019718.dbo.cfg_increase" indexname="PK__cfg_incr__3214EC07351DDF8C" id="lock12e75a280" mode="X" associatedObjectId="72057594111787008">
    <owner-list>
     <owner id="process20ec00bc8" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process9412988" mode="X" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>
 </deadlock>
</deadlock-list>

分析:因为key列无索引,更新需要使用id聚集索引去更新,导致更新请求更新锁时失败,引发死锁问题,

解决办法:

去除id列的聚集索引 ,在key 上建立聚集索引,更新通过key 更新表,解决问题。。。。

原文地址:https://www.cnblogs.com/niceletter/p/11227256.html

时间: 2024-07-31 21:40:34

记录一次高并发下由索引引发的死锁问题的相关文章

【开卷有益】记录一次高并发下的死锁解决思考过程

开卷有益,好久没写博客了,最近工作也挺忙的. 死锁距离我不遥远,终于还是在高并发时被我碰到了. DeadLock Found! 尽管编程风格中会尽量避免死锁,但是还是被我碰上了.文章可能看不出来我在做什么事情,只是记录自己的一个排除死锁的过程. 事情起源于两个联动的缓存+redis+异步数据库读写操作. 事务中的这句出现死锁: DELETE FROM table WHERE FROM key = 'helloworld' 当初的思考解除死锁的思路如下: 1)分析死锁模型,假设1,2 两个线程,假

记一个python+sqlalchemy+tornado的一个高并发下,产生重复记录的bug

场景:在用户通过支付通道支付完成返回时,发现我收到的处理数据记录中有两条同样的数据记录, 也就是同一笔钱,我数据库中记为了两条一样的记录. tornado端代码 from tornado import gen from tornado.concurrent import run_on_executor class processNetPay(BaseHandler): '''处理指定订单,指定支付请求,返回处理结果 ' 返回包含订单信息与用户信息体 ''' @tornado.web.asynch

高并发下问题随笔

高并发下随笔 随便写写,有什么不对的地方,请多指教. 选NGINX还是APACHE抗并发: 首先常用的架构是LNMP,之前用过LAMP的架构,但发现APACHE在高并发下表现并没有NGINX优异,原因是NGINX是异步非阻塞,APACHE是同步多进程阻塞型,NGINX会占用更少的资源抗并发,可能几千上万个链接依旧使用一个链接,NGINX也很容易组成集群, 给不同配置的服务器分配不同的权重,还包括负载均衡的方式,比如轮询与我们常用的IP_HASH等,所以推荐LNMP的架构. 选择HDD还是SSD硬

php结合redis实现高并发下的抢购、秒杀功能

原文: http://blog.csdn.net/nuli888/article/details/51865401 抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis.重点在于第二个问题 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问

高并发下的 Nginx 优化与负载均衡

高并发下的 Nginx 优化 英文原文:Optimizing Nginx for High Traffic Loads 过去谈过一些关于Nginx的常见问题; 其中有一些是关于如何优化Nginx. 很多Nginx新用户是从Apache迁移过来的,因些他们过去常常调整配置和执行魔术操作来确保服务器高效运行. 有一些坏消息要告诉你, 你不能像Apache一样优化Nginx.它没有魔术配置来减半负载或是让PHP运行速度加快一倍. 高兴的是, Nginx已经优化的非常好了. 当你决定使用Nginx并用a

高并发下的Nginx优化

高并发下的Nginx优化 2014-08-08 13:30 mood Nginx 过去谈过一些关于Nginx的常见问题; 其中有一些是关于如何优化Nginx. 很多Nginx新用户是从Apache迁移过来的,因些他们过去常常调整配置和执行魔术操作来确保服务器高效运行. AD:2014WOT全球软件技术峰会北京站 课程视频发布 11月21日-22日 与WOT技术大会相约深圳 现在抢票 过去谈过一些关于Nginx的常见问题; 其中有一些是关于如何优化Nginx. 很多Nginx新用户是从Apache

php 结合redis实现高并发下的抢购、秒杀功能

抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis.重点在于第二个问题 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数 [php] view plain copy <?php $conn=mysql_con

PHP开发中多种方案实现高并发下的抢购、秒杀功能

抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis. 重点在于第二个问题. 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数 <?php $conn=mysql_connect("localh

EF+MySQL乐观锁控制电商并发下单扣减库存,在高并发下的问题

下订单减库存的方式 现在,连农村的大姐都会用手机上淘宝购物了,相信电商对大家已经非常熟悉了,如果熟悉电商开发的同学,就知道在买家下单购买商品的时候,是需要扣减库存的,当然有2种扣减库存的方式, 一种是预扣库存,相当于锁定库存, 一种是直接扣减库存. 我们采用的是预扣库存的方式,预扣库存的时候,在SalesInfo表中,将最大可售数量MaxSalesNum减去购买数量,用一条SQL语句来表示这个业务,就是下面这个样子的: update salesinfo set MaxSalesNum=MaxSa