锁的细致分析

意向表的作用只是说当我们想锁全表的时候,避免给每一行都加X锁,而是直接相当于设置一个标识即可省去了开销
当前读:当前读就是说对于某条记录来说,如果没有别的事务对这条记录加锁,就把这条记录的最新版本读出来并且加锁,直到事务提交或者回滚时释放这个锁
快照读:通过undo实现
当前读:通过next-key 实现
其中快照读在RR和RC下不同,RR是读取的在读事务开始之后的快照版本,RC是读取该行记录的最新版本。
当前读是指读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析)
select * from table where ?;
当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。
select * from table where ? lock in share mode;
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;
所以针对当前读 在RC 和RR 情况下 分析锁的情况
如下两条sql语句:

SQL1:select * from t1 where id = 10;
SQL2:delete from t1 where id = 10;
在下面八种组合下,也就是RC,RR隔离级别下,SQL1:select操作均不加锁,采用的是快照读,因此在下面的讨论中就忽略了,主要讨论SQL2:delete操作的加锁。

组合一:id列是主键,RC隔离级别
主键加上X锁

组合二:id列是二级唯一索引,RC隔离级别
先给辅助索引加上X锁,再给主键索引加上X锁

组合三:id列是二级非唯一索引,RC隔离级别
与组合二一致,只是可能存储多条记录 所以多个记录被加上锁

组合四:id列上没有索引,RC隔离级别
锁全表(mysql后期优化为意向锁)
这是一个比较特殊的情况。id列上没有索引,where id = 10;这个过滤条件,没法通过索引进行过滤,那么只能走全表扫描做过滤
若id列上没有索引,SQL会走聚簇索引的全扫描进行过滤,由于过滤是由MySQL Server层面进行的。因此每条记录,无论是否满足条件,都会被加上X锁。但是,为了效率考量,MySQL做了优化,对于不满足条件的记录,会在判断后放锁,最终持有的,是满足条件的记录上的锁,但是不满足条件的记录上的加锁/放锁动作不会省略。同时,优化也违背了2PL的约束。

组合五:id列是主键,RR隔离级别
与组合一加锁一致

组合六:id列是二级唯一索引,RR隔离级别
与组合二一致

组合七:id列是二级非唯一索引,RR隔离级别
加入next-key=gap+record gap 锁住辅助索引前后记录的间隔,record 锁住对应的主键
这是为了防止幻读 如果不锁住gap,那么根据B+树的特性我们新增一个id=10 但是name=徐洁的 则辅助索引 就会插入
到我们刚刚的记录空隙间
从此特性可以看出 gap 只用于 非唯一索引


image.png

组合八:id列上没有索引,RR隔离级别
聚簇索引加上表锁,且每个记录直接的都加入了gap锁
组合九:Serializable隔离级别

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式。同时数据库又是个高并...
    CodeKing2017阅读 639评论 0 7
  • MySQL 加锁处理分析 转载2013年12月13日 16:43:55 7598 原文地址:http://hede...
    初来的雨天阅读 468评论 0 2
  • 背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题。我在工作过程中,经常会有同事咨询这方面的问题。...
    MakeACoder阅读 624评论 0 3
  • MySQL 的加锁处理分析 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题。我在工作过程中,经常会有...
    meng_philip123阅读 800评论 0 12
  • 我们的一生,没有既定结局,于是就没有所谓悲剧或喜剧,每个人都是新手,这条陌生的路,谁也不知道会通向哪里。
    昨日云烟阅读 264评论 0 0