zoukankan      html  css  js  c++  java
  • 死锁原因的排查

     


     

    1,打开跟踪,写入日志
    DBCC TRACEON (3605,1222,-1) –3605写入errorlog,1222死锁
    DBCC TRACEON(1222,-1) /若在启动时,加-T 1222
    同时,可开profile中的Deadlock graph跟踪,以图形化
    2,分析安装目录下生成的日志
       1)确定死锁的资源, 据对象不同查看方式不同。
    DBCC TRACEON(3604)

    DBCC PAGE(8,1,96,1)
    DBCC TRACEOFF(3604)

    死锁产生的前提:双方互占有了对方所需求的资源,若资源并不必要,可过滤掉。
    资源不必要:1)扫描了对方的资源,扫描过的就会加锁,避免被扫描到,如加索引等。
    3,死锁处理方法:
     1)从性能出发,优化sql
     2)从业务逻辑出发,看是否可去掉对死锁资料的关联。
     3)若还是不能解决,死锁是正常情况,避免不了,但可避免输出1205错误信息给客户端,方法就是加上try catch,可以等一会儿再重新执行。
    如:

    /*避免死锁显示给客户端 */
    DECLARE @retries INT ;
    SET @retries = 4 ;
    WHILE ( @retries > 0 )
        BEGIN
            BEGIN TRY
                BEGIN TRANSACTION ;
                -- place sql code here
                SET @retries = 0 ;
                COMMIT TRANSACTION ;
            END TRY
            BEGIN CATCH
                -- Error is a deadlock
                IF ( ERROR_NUMBER() = 1205 )
                    SET @retries = @retries - 1 ;
                    -- Error is not a deadlock
                ELSE
                    BEGIN
                        DECLARE @ErrorMessage NVARCHAR(4000) ;
                        DECLARE @ErrorSeverity INT ;
                        DECLARE @ErrorState INT ;
                        SELECT  @ErrorMessage = ERROR_MESSAGE() ,
                                @ErrorSeverity = ERROR_SEVERITY() ,
                                @ErrorState = ERROR_STATE() ;
                        -- Re-Raise the Error that caused the problem
                        RAISERROR (@ErrorMessage, -- Message text.
                        @ErrorSeverity, -- Severity.
                        @ErrorState -- State.
                        ) ;
                        SET @retries = 0 ;
                    END
                IF XACT_STATE() <> 0
                    ROLLBACK TRANSACTION ;
            END CATCH ;
        END ;
    GO
    
    /*死锁模拟
    1,建立数据
    2,连续两个事务
    */
    drop table Employee_Demo_Heap
    go
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [Employee_Demo_Heap](
    	[EmployeeID] [int] NOT NULL,
    	[NationalIDNumber] [nvarchar](15) NOT NULL,
    	[ContactID] [int] NOT NULL,
    	[LoginID] [nvarchar](256) NOT NULL,
    	[ManagerID] [int] NULL,
    	[Title] [nvarchar](50) NOT NULL,
    	[BirthDate] [datetime] NOT NULL,
    	[MaritalStatus] [nchar](1) NOT NULL,
    	[Gender] [nchar](1) NOT NULL,
    	[HireDate] [datetime] NOT NULL,
    	[ModifiedDate] [datetime] NOT NULL   DEFAULT (getdate()),
     CONSTRAINT [PK_Employee_EmployeeID_Demo_Heap] PRIMARY KEY nonCLUSTERED
    (
    	[EmployeeID] 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
    
    CREATE NONCLUSTERED INDEX [IX_Employee_ManagerID_Demo_Heap] ON [Employee_Demo_Heap]
    (
    	[ManagerID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    CREATE NONCLUSTERED INDEX [IX_Employee_ModifiedDate_Demo_Heap] ON [Employee_Demo_Heap]
    (
    	[ModifiedDate] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    GO
    insert into Employee_Demo_Heap
    select [EmployeeID] ,
    	[NationalIDNumber] ,
    	[ContactID] ,
    	[LoginID] ,
    	[ManagerID],
    	[Title] ,
    	[BirthDate] ,
    	[MaritalStatus] ,
    	[Gender] ,
    	[HireDate] ,
    	[ModifiedDate] from HumanResources.Employee
    go
    
    现在就用下面这组脚本模拟出一个死锁来。在一个连接里,运行下面的语句。反复开启事务。在这个事务里,先修改一条NationalIDNumber=‘480951955’的记录,然后再把它查询出来。做完以后,提交事务。
    set nocount on
    go
    while 1=1
    begin
    begin tran
    update dbo.Employee_Demo_Heap
    set BirthDate = getdate()
    where NationalIDNumber = '480951955'
    select * from dbo.Employee_Demo_Heap
    where NationalIDNumber = '480951955'
    commit tran
    end
    	在另外一个连接里,也运行这些语句。唯一的差别是这次修改和查询的是另一条NationalIDNumber = ‘407505660’的记录。
    set nocount on
    go
    while 1=1
    begin
    begin tran
    update dbo.Employee_Demo_Heap
    set BirthDate = getdate()
    where NationalIDNumber = '407505660'
    select * from dbo.Employee_Demo_Heap
    where NationalIDNumber = '407505660'
    commit tran
    end
  • 相关阅读:
    阿里云 CentOS 安装JDK
    【JSP&Servlet学习笔记】5.Servlet进阶AIP、过滤器与监听器
    【JSP&Servlet学习笔记】4.会话管理
    【HeadFirst设计模式】13.与设计模式相处
    【HeadFirst设计模式】12.复合模式
    【HeadFirst设计模式】11.代理模式
    【HeadFirst设计模式】10.状态模式
    【HeadFirst设计模式】9.迭代器与组合模式
    【HeadFirst设计模式】8.模板方法模式
    【HeadFirst设计模式】7.适配器模式与外观模式
  • 原文地址:https://www.cnblogs.com/heqianjin/p/5698606.html
Copyright © 2011-2022 走看看