zoukankan      html  css  js  c++  java
  • 如何阅读死锁日志

    一 前言
       
    工欲善其事必先利其器,前面分析了很多死锁案例,并没有详细的介绍如何通过死锁日志来诊断死锁的成因。本文将介绍如何读懂死锁日志,尽可能的获取信息来辅助我们解决死锁问题。
    二 日志分析
    2.1 场景 
    为了更好的学习死锁日志,我们需要提前了解死锁场景
    MySQL 5.6 事务隔离级别为RR

    1. CREATE TABLE `ty` (
    2.   `id` int(11) NOT NULL AUTO_INCREMENT,
    3.   `a` int(11) DEFAULT NULL,
    4.   `b` int(11) DEFAULT NULL,
    5.   PRIMARY KEY (`id`),
    6.   KEY `idxa` (`a`)
    7. ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4
    8. insert into ty(a,b) values(2,3),(5,4),(6,7);

    2.2 测试用例

    T2

    T1

    begin;

    delete from  ty where  a=5;

    begin;

    delete from  ty where  a=5;

    insert into ty(a,b) values(2,10);

    delete from  ty where  a=5;

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

                                                                
    2.3 我们通过show engine innodb status 查看的日志是最新一次记录死锁的日志。

    1. ------------------------
    2. LATEST DETECTED DEADLOCK
    3. ------------------------
    4. 2017-09-09 22:34:13 7f78eab82700
    5. *** (1) TRANSACTION: #事务1
    6. TRANSACTION 462308399, ACTIVE 33 sec starting index read
    7. mysql tables in use 1, locked 1
    8. LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
    9. MySQL thread id 3525577, OS thread handle 0x7f896cc4b700, query id 780039657 localhost root updating
    10. delete from ty where a=5
    11. *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    12. RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308399 lock_mode X waiting
    13. *** (2) TRANSACTION:
    14. TRANSACTION 462308398, ACTIVE 61 sec inserting, thread declared inside InnoDB 5000
    15. mysql tables in use 1, locked 1
    16. 5 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 2
    17. MySQL thread id 3525490, OS thread handle 0x7f78eab82700, query id 780039714 localhost root update
    18. insert into ty(a,b) values(2,10)
    19. *** (2) HOLDS THE LOCK(S):
    20. RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X
    21. *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
    22. RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X locks gap before rec insert intention waiting
    23. *** WE ROLL BACK TRANSACTION (1)

    2.4 日志分析
    *** (1) TRANSACTION: #事务1
    TRANSACTION 462308399, ACTIVE 33 sec starting index read 
    事务编号为 462308399 ,活跃33秒,starting index read 表示事务状态为根据索引读取数据。常见的其他状态:

    1. fetching rows 表示事务状态在row_search_for_mysql中被设置,表示正在查找记录。
    2. updating or deleting 表示事务已经真正进入了Update/delete的函数逻辑(row_update_for_mysql)
    3. thread declared inside InnoDB 说明事务已经进入innodb层。通常而言 不在innodb层的事务大部分是会被回滚的。

    mysql tables in use 1, 说明当前的事务使用一个表。locked 1 表示表上有一个表锁,对于DML语句为LOCK_IX
    LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
    LOCK WAIT表示正在等待锁, 2 lock struct(s) 表示trx->trx_locks锁链表的长度为2,每个链表节点代表该事务持有的一个锁结构,包括表锁,记录锁以及auto_inc锁等。本案例中2locks 表示IX锁和lock_mode X(Next-key lock)
    heap size 360 表示事务分配的锁堆内存大小,一般没有什么具体的用处。
    1 row lock(s)表示当前事务持有的行记录锁/gap 锁的个数。
    delete from ty where a=5 表示事务1在执行的sql ,不过比较悲伤的事情是show engine innodb status 是查看不到完整的事务的sql 的,通常显示当前正在等待锁的sql。
    *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308399 lock_mode X waiting
    RECORD LOCKS 表示记录锁,space id为219,page号4 ,n bits 72表示这个聚集索引记录锁结构上留有72个Bit位
    表示事务1 正在等待表 ty 上的 idxa 的 X 锁本案例中其实是Next-Key lock
    事务2的log 和上面分析类似,
    *** (2) HOLDS THE LOCK(S):
    RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X
    显示了事务2 insert into ty(a,b) values(2,10)持有了a=5 的Lock mode X |LOCK_GAP ,不过我们从日志里面看不到 事务2 执行的 delete from  ty where  a=5;这点也是造成DBA 仅仅根据日志难以分析死锁的问题的根本原因。
    *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X locks gap before rec insert intention waiting
    表示事务2的insert 语句正在等待插入意向锁 lock_mode X locks gap before rec insert intention waiting (LOCK_X + LOCK_REC_GAP )
    这里需要各位注意的是锁组合,类似lock_mode X waiting ,lock_mode X,lock_mode X locks gap before rec insert intention waiting 是我们分析死锁的核心重点。如何理解锁组合呢?
    首先我们要知道对于MySQL有两种常规锁模式
    LOCK_S(读锁,共享锁)
    LOCK_X(写锁,排它锁)
    最容易理解的锁模式,读加共享锁,写加排它锁.
    有如下几种锁的属性
    LOCK_REC_NOT_GAP        (锁记录)
    LOCK_GAP                       (锁记录前的GAP)
    LOCK_ORDINARY              (同时锁记录+记录前的GAP 。传说中的Next Key锁)
    LOCK_INSERT_INTENTION(插入意向锁,其实是特殊的GAP锁)
    锁的属性可以与锁模式任意组合。例如.
    lock->type_mode 可以是Lock_X 或者Lock_S 
    locks gap before rec  表示为gap锁:lock->type_mode & LOCK_GAP
    locks rec but not gap 表示为记录锁,非gap锁:lock->type_mode & LOCK_REC_NOT_GAP
    insert intention          表示为插入意向锁:lock->type_mode & LOCK_INSERT_INTENTION
    waiting                       表示锁等待:lock->type_mode & LOCK_WAIT

  • 相关阅读:
    Java实现 LeetCode 56 合并区间
    JQuery实现对html结点的操作(创建,添加,删除)
    JQuery实现对html结点的操作(创建,添加,删除)
    JQuery实现对html结点的操作(创建,添加,删除)
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 54 螺旋矩阵
    Java实现 LeetCode 54 螺旋矩阵
    Java实现 LeetCode 54 螺旋矩阵
  • 原文地址:https://www.cnblogs.com/liang545621/p/12613592.html
Copyright © 2011-2022 走看看