MySQL数据库之Purge死锁问题解析
作者:mrr 发布时间:2024-01-28 05:11:50
Purge死锁
场景说明
Purge死锁说明
表中存在记录(unique key) 10,20,30,40 (且有 自增主键 ),现在删除记录 20 ,并且已经 提交 了该事物。 purge 线程此时还 没有回收 该记录,且此时又 插入 新的记录 20 。
+------+------+------+------+
orignal | 10 | 20 | 30 | 40 |
unique +------+------+------+------+
delete 20 +------+------+------+------+
| 10 | 20* | 30 | 40 | (20 : delete-mark)
and commit +------+^----^+------+------+
| |
non happen | +--insert new 20
|
Purge
# 自增主键图中没有给出
回顾插入过程 完整的插入过程如下:
假设现在有记录 10,30,50,70 ;且为 unique key ,需要插入记录 25 。
1. 找到 小于等于25的记录 ,这里是 10
如果记录中已经 存在记录25 ,且带有 唯一性约束 ,则需要在 记录25 上增加 S Gap-lock (purge的案例中,老 记录20* 要加S lock的原因)
不直接报错退出或者提示已存在的原因,是因为有可能之前的 记录25 标记为删除( delete-mark ),然后等待 purge
如果 假设 这里 没有S Gap-Lock ,此时 记录30 上也 没有锁 的,按照下面的步骤,可以插入 两个25 ,这样就 破坏了唯一性约束
2. 找到 记录10的下一条记录 ,这里是 30
3. 判断 下一条记录30 上是否有锁(如果有=25的情况,后面再讨论)
判断 30 上面如果 没有锁 ,则 可以插入
判断 30 上面如果有 Record Lock ,则 可以插入
判断 30 上面如果有 Gap Lock / Next-Key Lock ,则无法插入,因为锁的范围是 (10, 30) / (10, 30] ;在 30 上增加 insert intention lock (此时处于 waiting 状态),当 Gap Lock / Next-Key Lock 释放时,等待的事物(transaction)将被 唤醒 ,此时 记录30 上才能获得 insert intention lock ,然后再插入 记录25
在这个场景中,新插入的记录 20 ,和已经存在的记录 20* 相等,且带有唯一约束,那此时就需要在记录 20* 上增加 S lock(with gap)
演示
因为要模拟插入记录 20* 的时候,老的 记录20 要存在,所以使用debug版本,将 purge线程停掉 。
[root@MyServer ~]> mysqld-debug --version
mysqld-debug Ver 5.7.11-debug for linux-glibc2.5 on x86_64 (MySQL Community Server - Debug (GPL))
[root@MyServer ~]> mysqld-debug --datadir=/data/mysql_data/5.7.11/ &
[1] 1493
[root@MyServer ~]> netstat -tunlp | grep 3306
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1493/mysqld-debug
--
-- 终端会话1
mysql> create table test_purge(a int auto_increment primary key, b int , unique key(b));
Query OK, 0 rows affected (0.20 sec)
mysql> insert into test_purge(b) values (10),(20),(30),(40);
Query OK, 4 rows affected (0.05 sec)
mysql> commit; -- autocommit=0 in my.cnf
Query OK, 0 rows affected (0.03 sec)
mysql> set global innodb_purge_stop_now=1;
-- show这个变量,结果还是off,这个不用管,purge线程已经停止了
Query OK, 0 rows affected (0.00 sec)
mysql> begin;
mysql> delete from test_purge where b=20;
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.02 sec)
-- 终端会话2
mysql> select * from test_purge;
+---+------+
| a | b | -- 20的那条记录已经删除,但是还没有被purge(purge线程停止)
| 1 | 10 |
| 3 | 30 |
| 4 | 40 |
3 rows in set (0.00 sec)
mysql> insert into test_purge(b) values(20);
Query OK, 1 row affected (0.04 sec)
-- 终端会话3
mysql> show engine innodb status\G
-- ----------------省略其他输出----------------
---TRANSACTION 9497, ACTIVE 19 sec
3 lock struct(s), heap size 1160, 3 row lock(s), undo log entries 1
MySQL thread id 3, OS thread handle 139922002294528, query id 26 localhost root cleaning up
TABLE LOCK table `burn_test`.`test_purge` trx id 9497 lock mode IX
RECORD LOCKS space id 47 page no 4 n bits 72 index b of table `burn_test`.`test_purge` trx id 9497 lock mode S -- S lock (with gap)
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
-- heap no=3表示是第二个插入的记录20
-- 且info bits为32,表示记录被标记删除了
0: len 4; hex 80000014; asc ;; -- 记录为20
1: len 4; hex 80000002; asc ;; -- 对应的主键为2
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
-- heap no=4表示的是20的下一个记录30
-- 且该记录上也有S lock
0: len 4; hex 8000001e; asc ;;
1: len 4; hex 80000003; asc ;;
RECORD LOCKS space id 47 page no 4 n bits 72 index b of table `burn_test`.`test_purge` trx id 9497 lock mode S locks gap before rec
Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 -- heap no=6为新插入的记录20,从隐式锁提升为显示锁
0: len 4; hex 80000014; asc ;;
1: len 4; hex 80000005; asc ;;
1. 因为是唯一索引,需要做唯一性检查,从老的记录 20* 开始检查(第一个小于等于自己的值),则此时 20* 上要加上一把 S lock ,然后往下检查到第一个不相等的记录,即 记录30 ,然后退出,但是这个 记录30 也要 加上S lock
2. 在插入 新的记录20 的时候,发现下一条记录30上有锁,则自己插入的时的 隐式锁 提升为 显示锁 (见插入步骤)
3. 目前锁住的范围是 (10,20], (20,30]
4. 新插入的记录20本身是一把 S-Gap Lock (前面20*的有S lock了,由于是唯一索引,本身其实就不需要有记录锁了,有GAP就够了)
所以记录25无法插入(锁等待)
mysql> insert into test_purge(b) values(25);
ERROR 1205 (HY000): Unknown error 1205 -- 等待了一段时间后,超时
---TRANSACTION 9508, ACTIVE 3 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1160, 1 row lock(s), undo log entries 1
MySQL thread id 5, OS thread handle 139922002560768, query id 46 localhost root update
insert into test_purge(b) values(25) -- 插入的25在等待
------- TRX HAS BEEN WAITING 3 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 47 page no 4 n bits 72 index b of table `burn_test`.`test_purge` trx id 9508 lock_mode X locks gap before rec insert intention waiting
------------------
TABLE LOCK table `burn_test`.`test_purge` trx id 9508 lock mode IX
---TRANSACTION 9503, ACTIVE 10 sec
MySQL thread id 7, OS thread handle 139922002028288, query id 44 localhost root cleaning up
TABLE LOCK table `burn_test`.`test_purge` trx id 9503 lock mode IX
RECORD LOCKS space id 47 page no 4 n bits 72 index b of table `burn_test`.`test_purge` trx id 9503 lock mode S
1: len 4; hex 80000002; asc ;;
RECORD LOCKS space id 47 page no 4 n bits 72 index b of table `burn_test`.`test_purge` trx id 9503 lock mode S locks gap before rec
Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
1: len 4; hex 80000007; asc ;;
这个例子中出现了 锁等待 ,就要 警惕 了,如果有 两个事物相互等待 ,就是 死锁 了
总结
以上所述是小编给大家介绍的MySQL数据库之Purge死锁问题解析网站的支持!
来源:https://mbrowser.baidu.com/web/landing/rssdetail?brand=feed_baijiahao&sid=TT_zonghe&nid=news_8976398819933547875


猜你喜欢
- 一、85%的广告没人看解读:如何挤进那15%的成功广告中去,吸引了读者就是成功了一半。Quester视角:反过来讲,只有不到1/5的广告能吸
- 学校让我们在放假期间自觉Python,对于Python我是小白的不能再小白了。一切从头开始,找学习资料,看视频教程光看书看视频也不行还要自己
- 一、文件操作pandas内置了10多种数据源读取函数,常见的就是CSV和EXCEL使用read_csv方法读取,结果为dataframe格式
- 之前上传图片都是直接将图片转化为io流传给服务器,没有用框架传图片。最近做项目,打算换个方法上传图片。Android发展到现在,Okhttp
- 过期软件破解方法: 如果你看到了这篇博文,绝对保证不虚此行。仅仅5行脚本代码,即可破解99%的过期软件。 &
- 在写论文时,如果是菜鸟级别,可能不会花太多时间去学latex,直接用word去写,但是这有一个问题,当我们用其他工具画完实验彩色图时,放到w
- 输入框Input 应当符合逻辑地划分为小组,这样大脑就可以很好的处理大堆区域间的关系。 ——《HTML权威指南》Web 应用程序总是利用表单
- 应用场景:状态不是200的URL重试多次代码比较简单还有部分注释python2.7实现:# -*-coding:utf-8-*-"
- 在java的应用中,我们经常会对数据库进行必要的操作,下来我们就了解一下如何用java连接mysql数据库 以及java连接sql serv
- //只能在firefox下运行 var test = { name: "puterjam", __noSuchMetho
- 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,对,你没猜错,相信自己的英语水平。先来一个简单
- 一、出错情况 有些时候当你重启了数据库服务,会发现有些数据库变成了正在恢复、置疑、可疑等情况,这个时候DBA就会很紧张了,下面是一些在实践中
- 在HeadFirstPython网站中下载所有文件,解压后以chapter 3中的“sketch.txt”为例: 新建IDLE会话
- 数据库事务隔离级别数据库事务的隔离级别有4个,由低到高依次为Read uncommitted:允许脏读。Read committed: 防止
- python面向对象编程入门,我们需要不断学习进步"""抽象工厂模式的实现"""
- 一、生成器1、生成器定义在Python中,一边循环一边计算的机制,称为生成器:generator2、生成器存在的意义列表所有数据都在内存中,
- 本文实例讲述了Python机器学习算法库scikit-learn学习之决策树实现方法。分享给大家供大家参考,具体如下:决策树决策树(DTs)
- 使用触发器触发器发生什么事情之后或之前,会自动执行某条语句,这就是触发器创建触发器创建触发器要给出的4条关键信息:1.唯一的触发器名2.触发
- 我们在使用bootstraptable做表格展示时,有时需要固定表格的高度当数据超出高度会出现滚动条,这时有可能出现表头列和数据列对不齐。出
- 一、进程与线程进程是操作系统资源分配的基本单位,是程序运行的实例。例如打开一个浏览器就开启了一个进程。线程是操作系统调度到CPU中执行的基本