【学习笔记】MySQL技术内幕InnoDB存储引擎——第6章 锁
第6章 锁
6.1 什么是锁
为保证一致性,对于共享资源设置锁机制
6.2 lock与latch
不同点:P251
6.3 InnoDB存储引擎中的锁
6.3.1 锁的类型
1>InnoDB的锁最低粒度为行级别的锁
2>共享锁:S Lock 读一行数据
排它锁:X Lock 允许事务删或改一行数据
3>InnoDB支持多粒度锁定,允许事务在行级上的锁和表级上的锁同时存在
InnoDB支持行锁与表级别意向锁,意向锁表示事务希望进一步加更细粒度的锁
意向锁兼容性:P253
【意向锁:意向锁其实是为了让已加行锁的表再加表锁时不必遍历每一行的行锁,而是直接查看意向锁的加锁情况,如果一张表有IX锁,那么显然不能再加表级别的S锁或者X锁】
6.3.2 一致性非锁定度
默认通过该方式:在加了X锁的情况下,读取时不会等待锁释放,而是直接读取undo段的快照数据。
MVCC:一行数据存在多个版本的记录数据(undo)【undo本身用来回滚数据,也可作为快照使用】
1>在读已提交隔离级别下,读取的快照为最新的undo记录
2>在可重复读隔离级别下,读取的快照为事务开始时的版本
6.3.3 一致性锁定读
可以使用 select ··· for update 加X锁读取
或者使用 select ··· lock in share mode 加S锁读取
6.3.4 自增长与锁
一开始通过一个对象为插入语句(不是事务)的表锁,后增加了互斥量。
6.3.5 外键和锁
当子表插入数据时,需要去主表查询,此时使用的是一致性锁定读,因为如果主表在删除,非锁定读之后是可以插入成功的,而删完之后主键不存在
6.4 锁的算法
6.4.1 行锁的3种算法
1>Record Lock:单个行记录上的锁
当使用的索引为唯一性索引时,默认使用行Record Lock
2>Gap Lock:间隙锁,锁定一个范围,不包括记录本身
3>Next-Key Lock:锁定一个范围+记录本身
6.4.2 解决Phantome Problem(幻读)
同一事务,执行两次同样的SQL导致不同结果
可重复度隔离级别下,使用间隙锁解决幻读问题
【如查询a>5,则间隙锁对[5,正无穷]加锁,a=6这种数据即不能插入】
读已提交下,存在幻读问题,不适用间隙锁
6.5 锁问题
6.5.1 脏读
读未提交才有的问题,读到了另一个事务未提交的数据,一般在主从复制的时候可以将从库表隔离级别设置为读未提交。(因为对查询要求不高,主要是备份)
6.5.2 不可重复度
不可重复度实际上是通过undo快照解决的,幻读是通过行锁+间隙锁解决的
6.5.3 丢失更新
如果对数据库进行查询并根据查询结果做后续DML SQL的话,需要对查询语句加For update,不然事务中查询到的值可能已经不是另一个事务提交后的值了。
6.6 阻塞
1>用户等待锁资源时会阻塞,当超过时会报异常,默认超时异常不回滚
2>用户需要尽量保证comimt或roll back,否则会导致不清楚SQL是否回滚的危险情况
6.7 死锁
6.7.1死锁的概念
两个或两个以上事务争夺资源而互相等待
1>超时回滚:超时便会回滚其中一个事务
2>wait-for graph(等待图)【InnoDB方式】
将事务等待其他事务释放资源用图表示,存在回路则说明死锁(P279)
6.7.2 死锁概率
1>事务越多死锁概率越大
2>事务操作的行越多,死锁概率越大
3>数据集合越小,概率越大
总的来时,死锁的概率是很小的。
6.7.3 死锁的实例
略
6.8 锁升级
SQL Server 对记录生产锁对象,开销大,会在对象被事务获取5000个锁以上或锁资源占内存40%以上时对锁进行升级(行锁->页锁->表锁)
InnoDB使用位图对每个页进行锁管理,消耗资源少,不会进行锁升级。