innodb加锁分析
这篇就是走了一遍登博的mysql加锁处理分析
基础知识请移步事务基础
快照读:简单的select操作,属于快照读,是不进行加锁的(也有例外,如Seriable隔离级下,应该是没有其他情况了)
当前读:
- lock in share mode;
- for update
- insert
- update
- delete
下边分析下这条语句的加锁情况:
delete from t1 where id = 10;
- 前提一:id列是不是主键?
- 前提二:当前系统的隔离级别是什么?
- 前提三:id列如果不是主键,那么id列上有索引吗?
- 前提四:id列上如果有二级索引,那么这个索引是唯一索引吗?
- 前提五:两个SQL的执行计划是什么?索引扫描?全表扫描?
下表中如无说明,加的锁类型都是X锁。
组合方式 | 加锁情况分析 | 备注 |
---|---|---|
id列是主键,RC隔离级别 | 加记录锁,锁主键,锁对应记录 | |
id列是二级唯一索引,RC隔离级别 | 加记录锁,锁主键和二级索引,锁对应的一条记录 | |
id列是二级非唯一索引,RC隔离级别 | 加记录锁,锁主键和二级索引,锁对应的几条记录 | |
id列上没有索引,RC隔离级别 | 加记录锁,锁所有记录,锁主键 | 若id列上没有索引,SQL会走聚簇索引的全扫描进行过滤,由于过滤是由MySQL Server层面进行的。因此每条记录,无论是否满足条件,都会被加上X锁。但是,为了效率考量,MySQL做了优化,对于不满足条件的记录,会在判断后放锁,最终持有的,是满足条件的记录上的锁,但是不满足条件的记录上的加锁/放锁动作不会省略。同时,优化也违背了2PL的约束。 |
id列是主键,RR隔离级别 | 加记录锁,锁主键,锁对应记录 | |
id列是二级唯一索引,RR隔离级别 | 加记录锁,锁主键和二级索引,锁对应记录 | |
id列是二级非唯一索引,RR隔离级别 | 二级索引上匹配的记录上加记录锁和二级索引匹配的记录间加GAP锁,对应的主键索引上加记录锁 | 1.GAP锁,就是RR隔离级别,相对于RC隔离级别,不会出现幻读的关键 |
id列上没有索引,RR隔离级别 | 匹配到的主键索引上记录锁,记录之间加GAP锁 | semi-consistent read开启的情况下,对于不满足查询条件的记录,MySQL会提前放锁 |