《MYSQL 插入意向锁死锁.docx》由会员分享,可在线阅读,更多相关《MYSQL 插入意向锁死锁.docx(5页珍藏版)》请在第一文库网上搜索。
1、插入意向锁死锁本章介绍种比较不常见的死锁现象,和我们通常理解的死锁发生过程不太样,能使读者对死锁现象有新的理解。问题现象死锁这种情况大家肯定都遇到过,第34章和第35章也介绍了两个死锁案例,本章的案例是客户在生产系统中遇到一个死锁现象,通常死锁发生的情况如图36-1所示。但是不能理解在这种情况下为何会发生死锁。图36-1 (图片来自网络)当两个事务都试图获取另一个事务已经拥有的锁时,就会发生死锁。事务 1 (Transaction 1)在记录A (Record A)上获得锁,事务2 (Transaction 2)在记录B (Record B)上获得锁。随后每个事务都尝试获取另一个事务持有的锁将
2、触发死锁。但在这个案例中死锁的产生和上述所讲的情况有些不一样,我们来模拟一下。(1)环境信息 事务隔离级别:RR MySQL版本:8.0.13(2)复现情况表结构及数据如下:mysql CREATE TABLE t (a INT UNSIGNED NOT NULL PRIMARY KEY, b INT);mysql INSERT INTO t VALUES(10,0),(20,0);操作步骤如表36-1所示。表36Sessicm 1Session 2BEGIN;UPDATE t SET b=l WHERE a=20;执行成功BEGIN;SELECT* FROM t LOCK IN SHARE
3、MODE;发生阻塞INSERT INTO t VALUES(lLl);/H ,口J刻Session 2报山死锁惜展SELECT * FROM t LOCK IN SHARE MODE;ERROR 1213 (4()001): Deadlock found when trying to getlock; try restarting transaction在Session 1中执行了UPDATE语句,随后在Session 2中执行了一个全表查询并且带上IN SHARE MODE添加了共享锁,接下来在Session 1中再次执行了INSERT语句,同时Session 2直接报出死锁事务被回滚了。问
4、题分析针对上述情况,令人疑惑的地方有如下几点: 两个事务之间是如何加锁的? 为何产生了死锁? 发生死锁后为什么是Session 2中的事务被回滚了?之前我们分析死锁问题都是通过查看死锁日志来进行的,这次我们使用MySQL 8.0中的performance.dataocks表,通过分析每一条语句执行后的加锁情况来分析这个死锁问题。两个事务之间是如何加锁的?当Session 1执行完UPDATE语句后,加锁情况如图36-2所示。| CWGXNC.IOCK.XO 1 ENGIME.TRANSACTXON.XO | THAO.XO | OB3CCT.SCHCRA | 0e3CT.NAM | XHDCX
5、.MAMC | LOCK.TYPt | LOCX.RODt110CK.STATUS | LOCK.DATA | 3ie33:MU|31G33 |S | dhy| t| NULL| TABLE| IX1GftANIEO| NULL| 3im:5$:4:3|31033 |56 | | XM.H0T.3 1GRANTtO1 ”112ai4797S9MMe8:lin12ai4797SM54e812 1|t1NULL1TA&LE1 IS1GRAMTED| KULL112ai47975MS498 :55:4:21“79759254081d”1t1PRXMAirr1WCOttO1 SIGRANTtO1112
6、tl479759eS4ee:5S:4:3“147975*5468dhy1tFRlMAtVlUCCMO1 51WAinilG1 ”图 36-3Session 2执行后总共会申请三个锁: 对表添加IS锁。对a= 10这条记录添加Next-Key Lock (S)锁。对a=20这条记录添加Next-Key Lock (S)锁。在第20章中我们介绍过LOCK_MODE各种显式结果对应的锁类型,这里的S锁代表的就是GAP锁+S记录锁的组合,等于Next-Key Lock (S)。在Session 2中执行会发生阻塞,因为在a=20这条记录上已经被Session 1持有的X锁与将要申请的S锁冲突。这里需要
7、注意Session 2执行完SELECT* FROM t LOCK IN SHAREMODE语句后上锁的类型应是Next-KeyLock (S)锁,这条语句锁定的范围是(-8,10,(10,20,(20,+oo)o由于在申请a=20记录上的S锁时发生了阻塞,我们看不到“supremumpseudo-record,如果单独执行这条语句,则加锁情况如图36-4所示。| w:IMIMf.TMSACTlON.ZO| VMttAO.ID IMXCV.SCMIMA |OBJtCT.MAHC| IHOVK.flAllf1tocM.rm1lOCA.NOOtLOCM.SVATUSLOCK.DATA| 2S147
8、99414TMn:l92123147994147367212 |dhy|t| MHX1TA8L1X$1GAAMED13 1| 3ai4m4147Mn: 3S141111B 16y1t|1tccow1s1UUNTID1112S1479941471721z 16y1t| WUMITV1MCOO1s1CAAMirO1It1R1KAR图36-4接下来在Session 1中执行INSERT语句添加插入意向锁(Insert Intention Lock),如图36-5所示。I EXMC.LOCX.XO |I ENGI帆 TRAMSACnOW.ID |TMRtAD.ro |1 083ECT. SCHEMA
9、| OtJECT.NARE| IMDU.MAM1LOCK.TYPtI 10CK.M00EI LOCK.STATVS | IQCR.DATA | 74M:im|)x I| Gy| t| MULL1TA8LC1 M| GKANTCO| MML| 2T4:3S:4:31274” |M |11 t| KU3TV1RECORD1 MnC,H0T,W| CRAHTtD| (| J744a:$:4:J I2744g |M |I dby1 C1 KU3VWC0M|(l,GA.!MSERT INTfNTXOMIl GRAMUD 1 ”|图36-5为何产生了死锁?我们看一下Next-Key Lock与插入意向锁的
10、兼容情况,如表36-2所示。表 36-2Next-Key I/xk (X)锁Next-Key Kock lock(x)记录锁Xa=10 - lock(s)a=2() - lock wait session 1NexlKeyLMA (S)锁插入意向馈Session 2等待Session 1中X锁的释放,随后的插入意向锁与Session 2中的Next-KeyLock (S)锁不兼容,这样就会造成Session 1与Session 2都不能继续执行,从而造成了死锁。发生死锁后为什么是Session 2中的事务被回滚了?当发生死锁时InnoDB选择回滚占用资源最少的事务,通过innodb_trx表中
11、的trx_weight来判断所占用资源的多少,此案例中单独执行SQL语电,通过查询innodbjrx表得知分别对应的trx_weight如表36-4所示,由于在Session 2中执行的SELECT语句对应的trx_weigt小于Session 1,所以Session 2中的事务被回滚。表 36-4语 句trx_weightUPDATE3ShUzCT2INSERT5本章小结在这个案例中我们分析了死锁的产生过程,案例中发生的死锁与通常的死锁不太一样,我们通过performance_schema.dataocks表来分析每一条语句执行后的加锁情况,最终分析出死锁的原因。案例中重点是分析插入意向锁与Next-Key Lock锁是否兼容。同时我们也知道了发生回滚时InnoDB是如何选择的。