广告位联系
返回顶部
分享到

MySQL锁等待和死锁问题怎么排查?show engine innodb status实战

Mysql 来源:互联网 作者:佚名 发布时间:2026-09-06 20:21:46 人浏览
摘要

锁的分类 乐观锁(S):读锁又叫共享锁,允许其他事物读不允许写 1 2 3 4 mysql8版本 SELECT * FROM USER FOR SHARE mysql8之前的版本 SELECT * FROM USER lock in share mode 悲观锁(X):写锁又叫排他锁,不允许

锁的分类

乐观锁(S):读锁又叫共享锁,允许其他事物读不允许写

1

2

3

4

mysql8版本

SELECT * FROM USER FOR SHARE

mysql8之前的版本

SELECT * FROM USER lock in share mode

悲观锁(X):写锁又叫排他锁,不允许其他事物读和写

1

SELECT * FROM USER FOR UPDATE

共享锁和共享锁之间不阻塞,共享锁和排他锁之间阻塞,排他锁和排他锁之间阻塞。

表锁:对表进行加锁,颗粒度大效率高并发低;MYISAM只有表锁

页锁:DBD引擎独有的。

行锁:InnoDB特有的,锁的是索引并不是行数据本身(索引项),当操作数据(update/delete)不是索引的时候,RR模式下会升级为表锁,RC不会升级;

意向锁:InnoDB引擎为了提高判断效率,对数据行加锁(锁的是索引那里)的时候引入了意向锁的概念

  • 即加一个行读锁的时候,同时记录一个IS,意向共享锁
  • 即加一个行写锁的时候,同时记录一个IX,意向排他锁

间隙锁(Gap Look):对操作的区间加一个开区间锁,RR隔离级别独有的,解决了幻读的问题

临键锁(Next-key Look):间隙锁+行锁组成的一个闭区间,

锁相关命令

1

2

3

4

5

6

7

8

-- 手动加表锁

lock 表名称 read/write,表2 read/write;

 

-- 查看表上加的锁 in_use 多少线程在使用 name_locked 是否加了锁

show open tables;

 

-- 删除表锁

unlock tables;

关于RR级别行锁升级为表锁的原因?

在RR隔离界级别下,为了防止出现不可重复读和幻读情况,在遍历聚集索引的时候,为了防止其他事物操作数据(不可重复读)和间隙被插入问题(幻读),导致数据不一致,因此会在所有扫描到的索引记录和间隙加上锁。

这并不是对整张表加锁,而是精确地对命中范围内的记录和间隙加锁。当然,如果部分记录已被其他事务加锁,也可能导致当前事务出现等待或死锁。

MYISM和InnDB在锁上的区别

MYISM在select的时候加表读锁,inster,update,delete的时候加表写锁;

InnoDB在执行select(非串行化隔离级别)的时候不加锁,在inster,update,delete的时候加行锁;

虽然在锁的性能开销上行锁更大, 但是整体使用上效率远远高于MYISM的表锁,也要使用得当,否则会出现死锁现象反而降低性能

锁等待分析

1

show variables like '%innodb_row_lock%'

对对应的状态进行分析,对于等待长次数高的,需要分析为什么会有这么多等待,然后优化。

查看近期的死锁日志:show engine innodb status;

1

2

3

4

5

6

7

8

9

10

查看事物

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;  // <8.0

查看锁

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; // <8.0

SELECT * FROM performance_schema.data_locks; // 8.0

查看锁等待

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; // <8.0

SELECT * FROM performance_schema.data_lock_waits; //8.0

释放锁

KILL trx_mysql_thread_id;

实际开发中注意事项

减少锁的范围颗粒度

降低事物隔离级别

进来用索引,防止锁升级

控制事物大小,设计锁资源的最后执行

MVCC(Multi-Version Concurrency Contorl)多版本并发控制

对同一行数据有不同的版本控制,可重复读和读已提交都是通过MVCC实现的;

undolog版本链和read view(一致性视图)机制:

不同事物会开启不同的版本链,在隐藏字段trx_id中存储,回滚标记roll_pointer,RR级别下,开启事物会生成 read view,后续操作不会改变(RC每次都生成新的read view);

这个read view是有,当前未提交的事物trx_id数组(数组里id最小的为min_id),和已创建的最大的事物trx_id(max_id)组成,任何事物查询都需要从版本链里最新数据逐一和read view对比从而获得最终的快照数据;

1

min_id= X; 未提交区间[*,*] ; max_id=Y;

比对规则:

  • 若trx_id<X,说明事物开始前提交的,可读。
  • trx_id>Y,说明在事物之后提交的,不可读(如果为自己当前事物的可读)。

若X<=trx_id>=Y,分为两种情况:

  • 如果在未提交区间[*,*]里,不可读(如果为自己当前事物的可读);
  • 如果不在未提交区间[*,*]里,表示已经提交可读

删除数据其实是update的一种特情况,首先会从版本链复制一份最新的,然后trx_id改成删除的trx_id,同时该记录的头信息标记delete_flag写成true,后续查询不返回;

注意:

begin/start transaction不是事物的起点,当执行修改操作或者排他锁的时候才会事物申请一个真正的事物id。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计