- 加锁过程
以记录锁为例,当对一条记录加写锁时,会向内存申请一个锁,然后看当前记录目前有什么锁,如果没有锁,或者兼容当前锁,锁的iswaiting项为false,然后操作记录,否则为true,在此等待。 - 各种语句分别加什么锁
select xxx 不加锁,快照读
select xxx in share mode 行共享锁 读意向锁
select xxx for update 行排它锁 写意向锁
update 行排它锁 写意向锁
delete 行排它锁 写意向锁
增删改查(或者说开启事务后第一次执行增删改查) 都会自动加元数据读锁(隐式锁),执行DDL语句加元数据写锁。元数据锁读读不互斥,读写互斥 - 什么时候释放锁
一般的锁,都是在事务提交后释放,元数据锁也是在释放,自增锁在插入完数据后释放 - 加什么样的行级锁
加锁的基本单位是混合锁 - 等值id查询
(1)读也能阻塞的例子 - (2) id为查询条件,等值查询,查到了
加的是记录锁
为什么?
因为加记录锁,锁住读取到的记录,就能避免该记录被删除 修改,进而保证相同sql语句前后读取一致,避免了幻读
如果 LOCK_MODE 为 X,说明是 next-key 锁;
如果 LOCK_MODE 为 X, REC_NOT_GAP,说明是记录锁;
如果 LOCK_MODE 为 X, GAP,说明是间隙锁(3) 等值查询,记录不存在的情况
加间隙锁
记录不存在,找到第一个比待查询id大的记录,加间隙锁,该id正好落在间隙内,防止插入,避免幻读
6. 唯一索引范围查询
针对扫描到的该范围内的非端点,都会加混合锁,端点根据情况讨论
(1) 大于
如果15不在表中,不会对15加锁,20是混合锁,如果在,也不会对15加锁
(2)大于等于
如果15在表格中,会对15加记录锁,如果不在?应该会在20加混合锁锁住(13,20](3) 小于
如果6不在表中,会对10(第一个比查询条件大的值)加间隙锁,锁住(5,10)
(4)小于等于,且条件不在表中
同小于
(5)小于,且查询条件值记录在表中
会对6加间隙锁(5)小于等于,且查询条件值记录在表中
会对6加混合锁
- 非唯一索引(可重复的二级索引)等值查询
(1)记录不存在
对第一个大于该值的二级索引记录加间隙锁,该间隙内不会在插入记录,避免幻读(没有聚簇索引记录,所以不用加锁)
(2)当记录存在时
在二级索引,会对比我打的第一条记录加间隙锁,其余符合条件的记录加混合锁
在聚簇索引,所有符合条件的记录加记录锁,防止删除,更改(为什么还对聚簇索引加锁,不是已经锁住二级索引了吗,我知道了,二级索引只能保证不插入等于25的新值(锁住区间了)不能修改索引列的值和主键列的值,不能保证修改其它列的值,这一点需要主键的记录锁保证)
- 什么时候插入记录不会阻塞,什么时候又不会阻塞
(1)主键不冲突,满足表约束,例如唯一性,非空等
(2)在1的前提下,在索引(聚簇和二级)中找到第一条比自己"大"的元素,如果其没有间隙锁,就能插入,如果有,不能 - 非唯一索引范围查询
会对所有符合条件的记录加混合锁 ,所有符合条件的聚簇索引加记录锁 - 非索引列查询