视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
sqlserver中死锁排查的全过程分享
2020-11-09 06:59:07 责编:小采
文档


前言

记得以前客户在使用软件时,有偶发出现死锁问题,因为发生的时间不确定,不好做问题的重现,当时解决问题有点棘手了。

死锁的四个必要条件:

  • 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
  • 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
  • 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
  • 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
  • 现总结下查看死锁的常用二种方式:

    第一种是图形化监听:

      sqlserver -->工具--> sql server profiler   登录后在跟踪属性中选择如下图:

      

       监听到的死锁图形如下图

       

    这里的描述大致是:有二个进程 一个进程ID是96, 另一个ID是348.   系统自动kill 掉了进程ID:96,保留了进程ID:348 的事务Commit。

    上面死锁是由于批量更新出现PAG范围锁, 双方进程在同一分区索引资源上。ID96,348都请求想获取更新锁(U),各占排它锁(x)不释放,直到锁超时。

    第二种是使用日志跟踪(errorlog)

    以全局方式打开指定的跟踪标记

            DBCC TRACEON(1222,-1)

           DBCC TRACEON(1204,-1)

    使用  EXEC master..xp_readerrorlog 查看日志。 由于记录的死锁信息太多,贴出几个重点说下(红色加粗表示)

    Deadlock encountered .... Printing deadlock information
    Wait-for graph
    NULL
    Node:1 
    PAGE: 7:1:6229275 CleanCnt:2 Mode:IX Flags: 0x3
    Grant List 3:
    Owner:0x00000004E99B7880 Mode: IX Flg:0x40 Ref:1 Life:02000000 SPID:219 ECID:0 XactLockInfo: 0x0000000575C7E970
    SPID: 219 ECID: 0 Statement Type: UPDATE Line #: 84
    Input Buf: Language Event: exec proc_PUB_StockDataImport
    Requested by: 
    ResType:LockOwner Stype:'OR'Xdes:0x0000000C7A905D30 Mode: U SPID: BatchID:0 ECID:59 TaskProxy:(0x0000000E440AAFE0) Value:0x8d160240 Cost:(0/0)
    NULL
    
    Node:2 
    PAGE: 7:1:5692366 CleanCnt:2 Mode:U Flags: 0x3
    Grant List 3:
    Owner:0x0000000D12099B80 Mode: U Flg:0x40 Ref:0 Life:00000001 SPID: ECID:0 XactLockInfo: 0x000000136B4758F0
    SPID:  ECID: 0 Statement Type: UPDATE Line #: 108
    Input Buf: RPC Event: Proc [Database Id = 7 Object Id = 907150277]

    -------- node:1 部分显示的几个关键信息:

     PAGE 7:1:6229275  (所在数据库ID 7, 1分区, 6229275行数)

     Mode: IX  锁的模式  意向排它锁

     SPID: 219  进程ID

     Event: exec proc_PUB_StockDataImport  执行的存储过程名

    -------node:2 部分显示的几个关键信息

     PAGE 7:1:5692366  (所在数据库ID 7, 1分区,5692366行数)

     Mode:U 锁的模式  更新锁

     RPC Event: Proc 远程调用

     SPID:   进程ID

    Victim Resource Owner:
    ResType:LockOwner Stype:'OR'Xdes:0x0000000C7A905D30 Mode: U SPID: BatchID:0 ECID:59 TaskProxy:(0x0000000E440AAFE0) Value:0x8d160240 Cost:(0/0)
    deadlock-list
    deadlock victim=process956f4c8
    process-list
    process id=process956f4c8 taskpriority=0 logused=0 waitresource=PAGE: 7:1:6229275 waittime=2034 ownerId=2988267079 transactionname=UPDATE 
    lasttranstarted=2018-04-19T13:54:00.360 XDES=0xc7a905d30 lockMode=U schedulerid=24 kpid=1308 status=suspended spid= sbid=0 ecid=59 priority=0 trancount=0 
    lastbatchstarted=2018-04-19T13:53:58.033 lastbatchcompleted=2018-04-19T13:53:58.033 clientapp=.Net SqlClient Data Provider hostname=VMSERVER76 hostpid=16328 
    isolationlevel=read committed (2) xactid=2988267079 currentdb=7 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
    executionStack
    frame procname=Test.dbo.proc_CnofStock line=108 stmtstart=9068 stmtend=9336 sqlhandle=0x03000700c503123601ba25019ca800000100000000000000
    update dbo.pub_stock
    set UpdateTime=GETDATE()
    from pub_stock a
    join PUB_PlatfromStocktemp b on a.GUID=b.StockGuid

       从上面的信息能看到kill 掉的是进程id是process956f4c8,

        进程spid=

        lockMode=U 获取更新锁

        isolationlevel=read committed

        executionStack 执行的堆信息:

                      存储名  procname=Test.dbo.proc_CnofStock

                      语句    update dbo.pub_stock set UpdateTime=GETDATE()   ..

        clientapp   发起事件的来源

    最后总结   避免死锁的解决方法

             按同一顺序访问对象。

            优化索引,避免全表扫描,减少锁的申请数目.

            避免事务中的用户交互。

            使用基于行版本控制的隔离级别。

             将事务默认隔离级别的已提交读改成快照

             SET TRANSACTION ISOLATION LEVEL SNAPSHOT

           使用nolock去掉共享锁,但死锁发生在u锁或x锁上,则nolock不起作用

           升级锁颗粒度(页锁,表锁), 以阻塞还代替死锁

    总结

    下载本文
    显示全文
    专题