加锁算法?
MySQL/mysql-storage-engines/innodb/1.5.5.InnoDB锁——lock之不同SQL加锁分析.md at master · asdbex1078/MySQL
抛开隔离级别谈上锁都是耍流氓!
读未提交
- 增:插入数据后,给新插入的数据上<font style="color:#DF2A3F;">记录锁</font>,防止其它事务更改这条记录
- 删:需要获取到要删除的记录的<font style="color:#DF2A3F;">记录锁</font>,保证删除的时候其它事务没在使用这些数据,并保证删除后其它事务无法对这些数据进行操作
- 改:给需要更改的数据上<font style="color:#DF2A3F;">记录锁 </font>
- 查:任何读都不加锁
读已提交
- 增:插入数据后,给新插入的数据上<font style="color:#DF2A3F;">记录锁</font>,防止其它事务更改这条记录
- 删:需要获取到要删除的记录的<font style="color:#DF2A3F;">记录锁</font>,保证删除的时候其它事务没在使用这些数据,并保证删除后其它事务无法对这些数据进行操作
- 改:给需要更改的数据上<font style="color:#DF2A3F;">记录锁 </font>
- 查:快照读不加锁,当前读只加记录锁
可重复读
- 增:使用<font style="color:#DF2A3F;">插入意向锁</font>,进行插入,插入后给插入的数据上<font style="color:#DF2A3F;">记录锁</font>(隐式锁,其实这个记录锁不是这个时候上的)
- 删:使用<font style="color:#DF2A3F;">临键锁</font>,防止其它事务在删除的区间内插入数据
- 改:给需要更改的数据上<font style="color:#DF2A3F;">临键锁 </font>
- 查:快照读不加锁,当前读:加临键锁和间隙锁,唯一索引则加记录锁
序列化
- 增:使用<font style="color:#DF2A3F;">插入意向锁</font>,进行插入,插入后给插入的数据上<font style="color:#DF2A3F;">记录锁</font>(隐式锁,其实这个记录锁不是这个时候上的)
- 删:使用<font style="color:#DF2A3F;">临键锁</font>,防止其它事务在删除的区间内插入数据
- 改:给需要更改的数据上<font style="color:#DF2A3F;">临键锁</font>
- 查:普通查询自动变为select … lock in share mode,上<font style="color:#DF2A3F;">临键锁,锁间隙</font>! 唯一索引加记录锁
细节
锁的对象是索引,而不是记录
二级索引的记录加了排他锁,聚簇索引也会加对应的锁。
如果没有合适的索引,那么MySQL就会扫表来处理,那么表的每一行都会被锁定,从而阻塞其他用户对 表的所有插入
临键锁只存在于可重复读和串行化事务隔离级别下
MVCC只存在于读已提交和可重复读
next-key lock 是前开后闭((x,y])区间,而间隙锁是前开后开区间((x,y))
临键锁上锁的优化:
临键锁锁的是一个间隙以及一个间隙后面的行记录,锁粒度比较大,在一些情况下会对其进行一定优化
总结起来就是 在加间隙锁or记录锁能避免幻读的情况下,临键锁就会退化成记录or间隙
唯一索引等值查询:
当查询的记录存在时,定位到了在索引树上的位置,那么原先在扫描时加的临键锁就会退化成记录锁
当查询的记录不存在时,在索引树找到比它大的第一条记录时,那么临建锁就会退化成 间隙锁

唯一索引范围查询情况
唯一索引扫描索引树时,会对扫描到的每一个索引加临键锁,如果满足一些条件就有可能发生锁退化
非唯一索引等值查询

非唯一索引范围查询情况
临键锁无法进行退化
非索引扫描情况
每一条记录的索引上都会加 next-key 锁,这样就相当于锁住的全表**:****从负无穷到正无穷(全表记**
录 + 所有间隙)
以上加锁的机制都是围绕着如何避免幻读来展开的
ps:锁全表的数据(临建锁)时,那这时候往表的最后一行后插入数据会被阻塞吗。会的,锁到正无穷,如果插入头部,负无穷也会被锁住

MySQL只操作同一条记录,也会发生死锁吗?
会的。mysql锁的是索引,而不是记录。如果是根据二级索引查询(加锁查询orDML),那么它会
先获取二级索引上的锁,然后再去对主键索引上的锁。如果有两线程同时获取锁的顺序不一样了,
那么就会发生死锁
加锁原则:两个原则两个优化一个bug