MVCC(多并发版本控制)介绍

当前读和快照读

当前读

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录(加锁)
  • select ... lock in share mode(共享锁)
  • select ...for update、update、insert、delete(排他锁)

快照读

简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,有可能是旧数据
  • RC隔离级别:每次执行select,都生成一个新的Read View,每次读取的数据都是最新数据
  • RR隔离级别:开启事务后第一个执行的select语句生成Read View,后面执行select都是使用第一次的Read View,读取的数据可能不是最新数据,实现了可重复读
  • 串行化隔离界别:快照读会退化为当前读(不存在多事务并发执行,所有读写都加表锁)

数据库并发场景有三种

  • 读-读:不存在任何问题,也不需要并发控制

  • 读-写:有线程安全问题,可能造成事务隔离性问题,有脏读,幻读,不可重复读问题(MVCC针对读写并发问题)

  • 写-写:有线程安全问题,可能会存在更新丢失问题

MVCC

多版本并发控制( Multi-Version Concurrency Control )

MVCC是指维护了一个数据的多个版本,为了实现 读写冲突不加锁,提高数据库的并发性能。
  • MVCC的实现依赖于三个隐藏字段、undo log和Read View来实现。
  • MVCC只存在于 RR 和 RC这两个隔离级别下。

聚集索引记录三个隐藏列

事务ID:每个事务开启时,都会被分配一个事务ID, 这个ID是递增的,所以最新的事务,ID值越大

  • DB_ROW_ID:隐藏主键,如果表没有指定主键,将会生成该隐藏字段(指定主键就不会添加该字段)

  • DB_TRX_ID:最近修改事务ID,记录插入该记录或最后一次修改该记录的事务ID

  • DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本的记录

undo log版本链

介绍

        不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,链表的头部是最新记录,链表尾部是最早的旧记录(使用头插法插入数据)

undo log日志(回滚日志)

在执行insert/update/delete时产生的便于数据回滚的日志,存储着修改数据的反向操作(逻辑日志)

有两个作用:事务回滚、MVCC(undo log版本链)

  • insert:产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除(还有活动的事务正在使用则不会删除)
  • update/delete:产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即删除。

undo log版本链的生成

有一张表的数据
idagenameDB_TRX_IDDB_ROLL_POINT
3030A301null
四个并发事务同时在访问这张表
事务1事务2事务3
开启事务开启事务开启事务
修改id=30的记录,age为3查询id为30的记录
提交事务修改id为30的记录,name为A3
提交事务
修改id=30的记录,age为10
查询id为30的记录
提交事务
        当事务1执行修改语句时,会记录undo log日志,记录数据变更之前的样子; 然后更新记录, 并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本。
        当事务2执行修改语句时,会记录undo log日志,记录数据变更之前的样子; 然后更新记录,并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本。

        当事务3执行修改语句时,会记录undo log日志,记录数据变更之前的样子; 然后更新记录,并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本。

Read View

Read View 介绍

Read View作用:决定快照读时,读取undo log版本链中的哪一个条记录

Read View是事务进行快照读操作时产生的读视图,记录并维护了当前活跃(未提交)的事务ID

生成ReadView的时机

  • RC:在事务中每一次执行快照读时生成ReadView。
  • RR:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

ReadView的核心字段

字段 含义
m_ids当前活跃的事务ID集合
min_trx_id最小活跃事务ID
max_trx_id预分配事务ID,当前最大事务ID + 1(因为事务ID是自增的)
creator_trx_idReadView创建者的事务ID
Read View中规定了版本链数据的访问规则( trx_id 代表当前undo log版本链上节点对应事务ID )
条件条件说明
trx_id==creator_trx_id
可以访问该版本
数据是当前这个事务更改的
trx_id < min_trx_id可以访问该版本数据已经提交了
trx_id > max_trx_id不可以访问该版本该事务是在ReadView生成后才开启
min_trx_id<= trx_id<=max_trx_id
如果trx_id不在m_ids中,可以访问该版本

如果条件成立,数据已经提交

        如果undo log版本链的头节点记录,四个条件判断后的结果都是不可访问,则根据回滚指针找到上一个版本的记录,继续判断,直到找到一个可以访问的记录。

RC和RR都是使用这个规则,只不过RC每次快照读都产生新Read View,而RR只会产生一次。

RC和RR级别快照读的不同

RC:读已提交

RR:可重复读

RC和RR区别是生成ReadView策略不同,从而导致RC、RR级别下快照读的结果不同

  • RC:每次快照读都会生成最新的的ReadView(提交的事务修改的数据一定能看到)

  • RR:同一个事务在第一次快照读的时候生成一个ReadView,之后的快照读都复用之前的ReadView

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙域、白泽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值