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


    先上一个存储过程

    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 depid=@depid;
                --    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="td2019718.dbo.GetNextIncrease" line="11" stmtstart="474" stmtend="606" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
    update cfg_increase set NextVal=(NextVal+1) WHERE [Key]=@key;     </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="td2019718.dbo.GetNextIncrease" line="8" stmtstart="242" stmtend="448" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
    select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key]=@key;
                --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="td2019718.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="td2019718.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="td2019718.dbo.GetNextIncrease" line="8" stmtstart="242" stmtend="448" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
    select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key]=@key;
                --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="td2019718.dbo.GetNextIncrease" line="11" stmtstart="474" stmtend="606" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
    update cfg_increase set NextVal=(NextVal+1) WHERE [Key]=@key;     </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="td2019718.dbo.GetNextIncrease" line="8" stmtstart="242" stmtend="448" sqlhandle="0x030009007a829c477a1b57016faa00000100000000000000">
    select @next=NextVal from cfg_increase with(xlock,rowlock)  where [Key]=@key;
                --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="td2019718.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="td2019718.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="td2019718.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 更新表,解决问题。。。。

  • 相关阅读:
    Codeforces Round #246 (Div. 2) —B. Football Kit
    expected expression __bridge
    ACM-百度之星资格赛之Energy Conversion——hdu4823
    xml解析-jaxp之dom解析
    NTP原理初步与配置
    Android开发学习之TabView选项卡具体解释 -- 基于Android4.4
    Apache轻量级性能測试工具--ab
    BAT的云
    03001_数据库
    ASP.NET调用dos命令获取交换机流量
  • 原文地址:https://www.cnblogs.com/niceletter/p/11227256.html
Copyright © 2020-2023  润新知