锁:为了支持对于共享资源的并发访问,提供数据的完整性和一致性。
1 lock vs latch (这一章讲的是lock)
lock 的对象是事务,用来锁定的是数据库中的对象,如表、页、行.
一般lock的对象仅在事务commit或者rollback后释放(不同隔离级别释放时间不同);
2 InnoDB中的锁
2.1. 锁的类型
- 行级锁:锁定索引
共享锁S:允许事务读一行数据。
排他所X:允许事务删除或更新一行数据。 - 意向锁:
支持在不同粒度上加锁,行级和表级上的锁同时存在。
InnoDB的意向锁就是表锁,主要是为了在一个事务中揭示下一行将被请求的锁类型;
意向共享锁 IS:事务想要获取一张表中的某几行的共享锁。
意向排他锁 IX:事务想要获取一张表中的某几行的排他锁。 -
IS IX S X IS 兼容 兼容 兼容 不兼容 IX 兼容 兼容 不兼容 不兼容 S 兼容 不兼容 兼容 不兼容 X 不兼容 不兼容 不兼容 不兼容 IS IX S X IS 兼容 兼容 兼容 不兼容 IX 兼容 兼容 不兼容 不兼容 S 兼容 不兼容 兼容 不兼容 X 不兼容 不兼容 不兼容 不兼容
2.2. 一致性非锁定读 MVCC
通过读取快照数据,实现读写并行;
1)快照数据是该行之前版本的数据,通过undo段来实现。而undo用来在事务中回滚数据,因此快照数据没有额外开销。此外,读取快照数据是不需要上锁的,因为没有事务需要对快照数据进行修改操作。
2)MVCC是默认的读取方式,即读取不会占用和等待表上的锁。
在不同的隔离级别下,读取的方式不同,并不是在每个事务隔离级别下都是采用MVCC读。
此外,即使都是MVCC读,对于快照数据的定义在不同隔离级别也各不相同。
- 隔离级别为可重复读时:InnoDB使用MVCC读,对于快照数据,总是读取事务开始时的行数据版本;
- 隔离级别为读已提交时:InnoDB使用MVCC读,对于快照数据,总是读取被锁定行的最新一份快照数据;
2.3. 一致性锁定读
某些情况下,需要显示对读取操作进行加锁以保证数据的一致性。 (隔离级别更高了,读也要加锁)
对select语句加X锁:select ... for update
对select语句加S锁:select ... lock in share mode
3 外键和锁
- Innodb中,对于外键列,如果没有显示加索引,会自动对其添加一个索引,因此避免表锁。
- 对于外键值的插入或更新,首先需要查询父表记录,select父表。此时并不是采用MVCC读的方式,而是选择了
select ... lock in share mode
主动对父表加S锁。如果此时父表上已经加X锁,子表操作被阻塞。
考虑:父表删除id操作,子表插入新纪录外键select父表选择MVCC就会产生不一致的情况。
4 行锁的算法
- Record Lock :单个行记录上的锁
- Gap Lock: 间隙锁,锁定一个范围,但不包含记录本身;(锁定的是两边的间隙,不能插进来)
- Next-Key Lock: Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。
辅助理解 MySQL 加锁处理分析
5 死锁
死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。
解决方法:
- 超时机制,优点是简单,缺点是未能考虑事务的执行情况。
-
等待图 wait-for-group ,InnoDB采取这种方式。
等待图 要求数据库保留两种信息:锁的事务链表,事务等待链表。
根据上述信息构造出一张图,如果存在回路代表存在死锁。
图中,事务1指向事务2的边定义为:
(1)事务1等待被事务2所占用的资源;
(2)事务1最终等待事务2所占用的资源,即事务12在等待相同的资源,而事务1在事务2后边;
等待图是一种主动的死锁检测机制,每个事务请求锁的时候都会判断是否存在回路,若存在则死锁,通常InnoDB选择回滚undo量最小的事务。
6 补充总结
- MySQL Innodb存储引擎的并发控制方式:Lock-Based Concurrency Control + MVCC
在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。 -
2PL:Two-Phase Locking
传统RDBMS加锁的一个原则,就是2PL (二阶段锁):Two-Phase Locking。
锁操作分为两个阶段:加锁阶段与解锁阶段,并且保证加锁阶段与解锁阶段不相交。
2PL就是将加锁/解锁分为两个完全不相交的阶段。加锁阶段:只加锁,不放锁。解锁阶段:只放锁,不加锁。 - 分析SQL语句加锁情况:MySQL 加锁处理分析
- 参考书《MySQL技术内幕 InnoDB存储引擎 第2版》
@梦工厂 2018.3.16
网友评论