目录并发
事物之间产生加锁的循环等待,造成死锁this
LOCK_X(写锁,排它锁)code
LOCK_INSERT_INTETION(插入意向锁)blog
能够任意组合索引
根据主键查找-锁加在主键上
如 begin;select * from tt_copy where id=4 for update;
加锁状况事务index PRIMARY of table
test
.tt_copy
trx id 1101588 lock_mode X locks rec but not gapit
根据普通索引查找-锁加在普通索引和主键上
如 begin;select * from tt_copy force index(idx_a) where a=4 for update;
加锁状况ioindex idx_a of table
test
.tt_copy
trx id 1101590 lock_mode X locks rec but not gap
index PRIMARY of tabletest
.tt_copy
trx id 1101590 lock_mode X locks rec but not gapinnodb
如下没特殊说明都为RC隔离级别event
有Unique key
插入前,惟一约束检查:LOCK_S+LOCK_ORDINARY
插入前,插入的位置有GAP锁:LOCK_INSERT_INTETION
插入后,新数据插入:LOCK_X+LOCK_REC_NOT_GAP
知足删除条件的全部记录:LOCK_X+LOCK_REC_NOT_GAP
Update操做分解
- Step 1:定位到 下一条知足查询条件的记录(查询过程,相似于Select/Delete)
- Step 2:删除当前定位到的记录(标记为删除状态)
- Step 3:拼装更新后项,根据更新后项定位到 新的插入位置
- Step 4:在新的插入位置,判断是否存在 Unique 冲突( 存在Unique Key 时)
- Step 5:插入更新后项(不存在Unique冲突时)
- Step 6: 重复Step 1 到Step 5 的操做,直至扫描完整个查询范围
Update操做分析
- Step 1,Step 2:Delete
- Step 3,Step 4,Step 5:Insert
Update
无Unique key:
- 查询范围中的全部记录,LOCK_X + LOCK_REC_NOT_GAP
有Unique key:
- 查找知足条件的记录:查询范围内的全部记录, LOCK_X + LOCK_REC_NOT_GAP
- 更新后项存在惟一性冲突:冲突项上的加锁,LOCK_S + LOCK_ORDINARY
- 更新后项不存在惟一性冲突: 更新位置后项加锁,LOCK_S + LOCK_GAP (省略)
- 实际更新操做:可看作插入了一条新纪录,LOCK_X + LOCK_REC_NOT_GAP
- Read Committed (RC) ) :Unique Key 惟一约束检查;Purge操做;
- Repeatable Read (RC ):RC的基础上,全部须要加锁的索引范围扫描和索引查找(Update/Delete…)
- 还有一种会加GAP锁:RR隔离级别下,对有惟一索引的表执行insert on duplicate update操做,除了会对新插入的记录加x not gap外,还会对相邻记录加x gap
change the transaction isolation level to READ COMMITTED or enable the innodb_locks_unsafe_for_binlog system variable (which is now deprecated)
By default, InnoDB operates in REPEATABLE READ transaction isolation level. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rows
An insert intention lock is a type of gap lock set by INSERT operations prior to(在...以前) row insertion.
• 原则之一
- 要分析一个死锁,必须深刻业务,了解整个事务的逻辑(闭门没法造车)
• 原则之二`
- GAP锁很复杂,为了减小GAP锁,减小GAP致使的死锁,尽可能选择Read Committed隔离级别(RC + row based binlog,基本上可以解决全部问题,无需使用Repeatable Read)
- 适当的 减小Unique 索引,可以减小GAP锁致使的死锁(根据业务状况而定)
• 原则之三
- 在MySQL 中,以不一样索引的过滤条件, 来操做相同的记录(Update/Delete ),很容易产生死
锁。
• 原则之四
- RC隔离级别下,若是死锁中出现Next Key(Gap锁),说明表中必定存在unique索引
- 多语句事务产生的死锁,确保每条语句操做记录的顺序性,可以极大减小死锁
本文大多数都整理自《死锁-何登成 - 管中窥豹——MySQL(InnoDB)死锁分析之道》