0%

CannotAcquireLockException--LockAcquisitionException

文章字数:411,阅读全文大约需要1分钟

sqlServer数据库环境下出现CannotAcquireLockExceptionLockAcquisitionException异常,记录排查过程

排查过程

  1. 期初以为是接口执行时间过长,导致其它事务获取不到锁导致的。之后模拟锁表,结果发现锁了好几分钟的情况下其他事务都会自旋等待,直到获取到锁才会继续执行。
    结果就是手动加锁只会让接口执行时间边长,并不会抛出上述异常。
  2. 搜索了一下上述异常,发现死锁才会抛出这个异常。之前的尝试最多是等待超时,死锁需要两个事物彼此等待。
  3. 还原发生异常的现场数据,并且运行了一下。发现下发命令的接口执行一分钟左右就会抛出异常。
  4. 使用客户端连接数据库,在程序运行时手动运行以下sql
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    SELECT  
    der.[session_id],der.[blocking_session_id],
    sp.lastwaittype,sp.hostname,sp.program_name,sp.loginame,
    der.[start_time] AS '开始时间',
    der.[status] AS '状态',
    dest.[text] AS 'sql语句',
    DB_NAME(der.[database_id]) AS '数据库名',
    der.[wait_type] AS '等待资源类型',
    der.[wait_time] AS '等待时间',
    der.[wait_resource] AS '等待的资源',
    der.[logical_reads] AS '逻辑读次数'
    FROM sys.[dm_exec_requests] AS der
    INNER JOIN master.dbo.sysprocesses AS sp ON der.session_id=sp.spid
    CROSS APPLY sys.[dm_exec_sql_text](der.[sql_handle]) AS dest
    --WHERE [session_id]>50 AND session_id<>@@SPID
    ORDER BY der.[session_id]
    GO
  5. 最后在抛出异常前发现两个互锁的事务
session_id blocking_session_id
1 2
2 1
  1. 通过查询出来的session_idblocking_session_id可以看出两个事物形成了死锁
  2. 再通过查询出的sql语句定位到具体代码(具体操作要看业务逻辑)
  3. 通过报错下的调用栈也可以定位到其中一条sql语句的位置。

分析

两张表同时被两个事物先后访问,并分别加锁。导致锁表