暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL死锁日志分析入门之如何看懂阅读日志

菜鸟DBA 2021-04-13
5078

一、背景说明

        最近很多小伙伴因为数据库死锁的问题而烦恼,本文将着重介绍如何阅读、理解MySQL数据库的死锁日志,更好的分析死锁问题,解决问题。

   

二、环境以及测试案例

 2.1  环境

        本文采取MySQL5.7的RR模式下为案例进行解析

2.2  案例表结构以及数据

        

    create table t2(

        id int(11) not null auto_increment,

        c1 varchar(20) default null,

        c2 varchar(20) default null,

        primary key(id),

        key idx_c1(c1)

        )engine=INNODB auto_increment=1 default charset=utf8mb4

insert into t2(c1,c2) values('asd','people'),('aud','jian'),('mou','longjian'),('cmn','python3');

  2.3 测试案例

           

T1
T2
begin;
begin;
delete from t2 where c1='asd';null
null
delete from t2 where c1='asd';
insert into t2 (c1,c2) values ('aaa','mmm')

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


三、 通过show engine ennodb status\G;获取MySQL 的死锁信息

死锁日志以及死锁分析(分析日志#开始)

        

LATEST DETECTED DEADLOCK   ###最后一次死锁的信息

------------------------

2020-06-30 11:52:49 0x7fb5531fa700  ###死锁发生的时间

*** (1) TRANSACTION:   ##事务一

TRANSACTION 11435982, ##事务编号 ACTIVE 38 ##活跃时长以s计算  sec starting index read ##事务正在进行的状态,本案例显示正在读取索引数据

mysql tables in use 1, locked 1 ##当前事务有一个表上有锁,并且是一把锁

LOCK WAIT 2 lock struct(s), ##表示锁等待 size 1136, ##事务执行中分配给锁的内存大小,1 row lock(s)##当前事务持有锁的个数

MySQL thread id 52, ##表示MySQL的进程ID

OS thread handle 140416759858944, 

query id 1983 ###表示SQL的id 

localhost root updating ##表示root@'localhost'执行的 update操作

delete from t2 where c1='asd'  ###表示事务中正在执行(等待)的SQL

##通常情况下通过show engine innodb 不能拿到完整的事务的信息,这个给DBA排查问题增加了不少麻烦,需要跟研发沟通结合SQL审计找出此事务的全部SQL

*** (1) WAITING FOR THIS LOCK TO BE GRANTED: ##等待后去这个锁

RECORD LOCKS #记录锁 space id 181 page no 4 ##记录space id 为181,page序号为4(一般跟事务2上的hold lock信息相互对应)

 n bits 80 index idx_c1 of table `test`.`t2` trx id 11435982 lock_mode X waiting

###说明等待test库t2表上的idx_c1索引的X 锁

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32 ##表示记录锁的物理记录信息

 0: len 3; hex 617364; asc asd;;

 1: len 4; hex 80000002; asc     ;;

##表示记录锁的字段信息 ##对应表中字段的值,存储为16进制,可以解析为十进制来对应表中锁的数据


*** (2) TRANSACTION:

TRANSACTION 11435977, ACTIVE 51 sec inserting

mysql tables in use 1, locked 1

5 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 2

MySQL thread id 51, OS thread handle 140416760391424, query id 1984 localhost root update

##与上面分析类似

insert into t2 (c1,c2) values ('aaa','mmm')

*** (2) HOLDS THE LOCK(S): ##事务2已经获取的锁信息、与上面分析类同

RECORD LOCKS space id 181 page no 4 n bits 80 index idx_c1 of table `test`.`t2` trx id 11435977 lock_mode X

###表示目前拥有这行的数据记录锁

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32

 0: len 3; hex 617364; asc asd;; 

 1: len 4; hex 80000002; asc     ;;


###与事务一类同


*** (2) WAITING FOR THIS LOCK TO BE GRANTED: ##事务2等待获取的锁信

RECORD LOCKS space id 181 page no 4 n bits 80 index idx_c1 of table `test`.`t2` trx id 11435977 lock_mode X locks gap before rec insert intention waiting ###表示等待获取gap锁,在RR模式下GAP锁,insert数据过程中会有lock x锁+ next key锁的组合操作

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32

 0: len 3; hex 617364; asc asd;;

 1: len 4; hex 80000002; asc     ;;


*** WE ROLL BACK TRANSACTION (1)

##结果回滚了事务1


四、总结

    常见避免死锁的方法

  • 合理创建索引,复合索引区分度比较高的字段放在最前,

  • 优化SQL执行顺序,持有锁比较频繁或者时间长的SQL放在事务最后面

  • 拆分大事务为小事务

  • 尽可能以固定的顺序访问表

  • 调整mysql事务隔离级别,默认为RR调整为RC 减少锁竞争

    







文章转载自菜鸟DBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论