一条简单update语句,mysql锁操作

目录

  • 前置知识
  • 实例分析加锁情况

todo 结合参考文章0和参考文章1重新梳理下, ACID, explain分析

  • 深入篇可以总结下https://www.jianshu.com/p/945d391f9ef0
  • redo log undo log
  • orderby limit为什么有时候返回值不同,因为非稳定性算法比如快排排序,orderby的列不唯一,加个唯一列比如id就好
  • mvcc在select insert(事务2) update select不能解决幻读RR级别下,可以找下资料总结

前置知识

MVCC多版本并发控制
  • MVCC(Multi-Version Concurrency Control): 读不加锁,读写不冲突。同一份数据临时保存多个版本的一种方式,进而实现并发控制。 MVCC分两类
  1. 快照读: 读取的是记录中的可见版本(可能是历史版本, 可以简单理解为每条记录多一个version字段,每次更新都会操作这个version。),不用加锁。
  2. 当前读(特殊的select操作、insert、delete和update):读取的是记录中最新版本,并且当前读返回的记录都会加上锁,这样保证了了其他事务不会再并发修改这条记录。
聚集索引
  • 完整的记录,储存在主键索引中,通过主键索引,就可以获取记录中所有的列。非聚集索引就需要回表查数据。
隔离级别
  • Read Uncommitted:可以读取未提交记录。存在脏读,不可重复读,幻读现象。此隔离级别一般不会使用。
  • Read Committed(RC): 解决了脏读,存在不可重复读,幻读现象
  • Repeatable Read(RR): 解决了不可重复读,存在幻读现象。可重复读主要是针对其他事务的update与delete不会对本事务产生影响,而其他事务的insert操作对本事务的查询产生影响则称为幻读。
  • Serializable:从MVCC并发控制退化为基于锁的并发控制。
InnoDB中完整行锁
  • 记录锁(Record Lock):记录锁锁定索引中的一条记录
  • 间隙锁(Gap Lock):间隙锁要么锁住索引记录中间的值,要么锁住第一个索引记录前面的值或最后一个索引记录后面的值。
  • Next-Key Lock:Next-Key锁时索引记录上的记录锁和在记录之前的间隙锁的组合。

实例分析加锁情况

/**
* table T (id int, name varchar(20));执行的是delete语句,下面展示了RR避免可重复读的方式
* 如果是insert语句,则不同事务有可能出现幻读可以通过for update形式避免,for update在 
* insert形式无数据情况下会加gap锁, 实例分析参考参考文章2.InnoDB Gap锁
**/
delete from T where id = 10;
id为主键 + RC/RR
  • id是主键时,执行该语句时,只需要将主键id = 10的记录加上写锁
id唯一索引 + RC/RR
  • 由于id是唯一索引,因此delete语句会选择走id列的索引进行where条件过滤,在找到id = 10的记录后,首先会将唯一索引上的id = 10的记录加上X锁,同时,会根据读取到的name列,回到主键索引(聚簇索引),然后将聚簇索引上的name 对应的主键索引项加写锁。唯一索引只有一条记录相对应,所以查询只会返回一条记录。
id不唯一索引+RC
  • 若id列上有非唯一索引,那么对应的所有满足SQL查询条件的记录,都会加上锁。同时,这些记录在主键索引上也会加上锁。
id无索引+RC
  • 若id列上没有索引,MySQL会走聚簇索引进行全表扫描过滤。由于是在MySQl Server层面进行的。因此每条记录无论是否满足条件,都会加上X锁,但是,为了效率考虑,MySQL在这方面进行了改进,在扫描过程中,若记录不满足过滤条件,会进行解锁操作。
id不唯一索引+RR
  • 在RR隔离级别下,id列上有非唯一索引,对于上述的SQL语句;首先,通过id索引定位到第一条满足条件的记录,给记录加上X锁,并且给其Gap加上Gap锁,然后在主键聚簇索引上满足相同条件的记录加上X锁,然后返回;之后读取下一条记录重复进行。直至第一条出现不满足条件的记录,此时,不需要给记录加上X锁,但是需要给其Gap加上Gap锁吗,最后返回结果。


    加锁分析.png
id无索引+RR
  • 在Repeatable Read隔离级别下,如果进行全表扫描的当前读,那么会锁上表上的所有记录,并且所有的Gap加上Gap锁。
  • 当然在MySQL中,可以触发 semi-consistent read来缓解锁开销与并发影响,但是semi-consistent read本身也会带来其他的问题,不建议使用。

参考文章

  1. 对于MVCC以及如何在RR上解决幻读的理解
  2. 一条简单的更新语句,MySQL是如何加锁的?
  3. InnoDB Gap锁
  4. 【性能优化实战】4次版本迭代,我们将项目性能提升了360倍!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。