MySQL-当前读、快照读、MVCC

2020-01-08  本文已影响0人  Tian_Peng

前言:事务的开启与提交模式

对于一个MYSQL数据库(InnoDB),事务的开启与提交模式无非下面这两种情况:

1. 当前读

当前读,读取的是最新版本,并且对读取的记录加锁,阻塞其他事务同时改动相同记录,避免出现安全问题。

1.1哪些形式的SQL属于当前读:

例如,假设要update一条记录,但是另一个事务已经delete这条数据并且commit了,如果不加锁就会产生冲突。
所以update的时候肯定要是当前读,得到最新的信息并且锁定相应的记录。

关于for update

利用select * for update 可以锁表/锁行。
自然锁表的压力远大于锁行。所以我们应尽量采用锁行。
FOR UPDATE仅适用于InnoDB,且必须在事务处理模块(BEGIN/COMMIT)中才能生效
那么什么时候锁表呢?

1.2当前读的实现方式

当前读使用next-key锁(行记录锁+Gap间隙锁)实现
间隙锁:只有在Read Repeatable、Serializable隔离级别才有,就是锁定范围空间的数据,假设id有3,4,5,锁定id>3的数据,是指的4,5及后面的数字都会被锁定,因为此时如果不锁定没有的数据,例如当加入了新的数据id=6,就会出现幻读,间隙锁避免了幻读。

2. 快照读

单纯的select操作,不包括上述 select ... lock in share mode, select ... for update。    
Read Committed隔离级别:每次select都生成一个快照读
Read Repeatable隔离级别:开启事务后第一个select语句才是快照读的地方,而不是一开启事务就快照读

快照读的实现方式:undolog和多版本并发控制MVCC

下图右侧绿色的是数据:一行数据记录,主键ID是10,name='Jack',age=10, 被update更新set为name= 'Tom',age=23。
事务会先使用“排他锁”锁定该行,将该行当前的值复制到undo log中,然后再真正地修改当前行的值,最后填写事务的DB_TRX_ID,使用回滚指针DB_ROLL_PTR指向undo log中修改前的行DB_ROW_ID

image
上一篇 下一篇

猜你喜欢

热点阅读