一.MySQL常用存储引擎的锁机制
- Myisam和Memory默认采用表级锁(table-level locking)
- BDB采用页面锁(page-level locking)或表级锁,默认为页面锁
- Innodb支持行级锁(row-level locking)和表级锁, 默认为行级锁 (偏向于写)
Innodb 四种锁定模式的共存逻辑关系 :
共享锁(S) | 排他锁(X) | 意向共享锁(IS) | 意向排他锁(Ⅸ) | |
---|---|---|---|---|
共享锁(S) | 兼容 | 冲突 | 兼容 | 冲突 |
排他锁(X) | 冲突 | 冲突 | 冲突 | 冲突 |
意向共享锁(IS) | 兼容 | 冲突 | 兼容 | 兼容 |
意向排他锁(Ⅸ) | 冲突 | 冲突 | 兼容 | 兼容 |
如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放
二.三种行锁算法
1.Innodb 有三种行锁算法, 并且都属于排它锁
- Record Lock : 单个行记录上的锁
- Gap Lock : 间隙锁, 锁定一个范围, 但不包括记录本身; GAP锁的目的, 是为了防止同一事务的两次当前读, 出现幻读的情况
- Next-Key Lock : 等于Record Lock结合Gap Lock, 也就说Next-Key Lock既锁定记录本身也锁定一个范围, 特别需要注意的是, InnoDB存储引擎还会对辅助索引下一个键值加上gap lock
2.什么是间隙锁
- 当我们用范围条件而不是相等条件检索数据, 并请求共享或排他锁时, InnoDB会给符合条件的已有数据记录的索引项加锁
- 对于键值在条件范围内但并不存在的记录, 叫做"间隙 (GAP)", InnoDB也会对这个"间隙"加锁, 这种锁机制就是所谓的间隙锁 (Next-Key锁)
- 示例 : 假设 emp 表中的有100条数据, 当使用
select * from emp where id>=100 for update;
语句的时候, 它是一个范围条件检索, 并且命中了索引, InnoDB不仅会对符合条件的emp_id值为100的记录加锁, 也会对em_pid大于100 (这些记录并不存在) 的"间隙"加锁
ps : 对于行的查询, Innodb采用的都是Next-Key Lock, 主要目的是解决幻读的问题, 以满足相关隔离级别以及恢复和复制的需要