MVCC机制

产生MVCC原因

由于加锁的串行化执行太慢,MVCC机制诞生,在读已提交,和可重复读中使用. 只有innodb可以,由于这个特性默认的可重复读还解决了幻读问题.

使用场景:

并发事务大致可以分为4类,读读,写写,读写,写读。读读不会影响数据。

  • 读读场景:不会引起数据的变化,不用做任何处理。
  • 写写场景:会有更新覆盖的问题,需要进行处理,需要进行上锁处理。
  • 读写写读场景:两种类似,写读,会有脏读,不可重复读,幻读出现,需要处理,使用的是mvcc机制处理。

MVCC机制:

多版本并发控制技术,数据行的多个版本,主要用来提升数据库性能设计的,处理读写并发冲突。主要是在InnoDB中使用。
MySQL中仅在RC读已提交级别、RR可重复读级别才会使用MVCC机制。
readview:进行版本管理,更够读取到数据行历史的值.
undolog:保存历史数据
image.png
隐藏字段:用于辅助

实现原理-三种支持技术:

通过MVCC机制的隐藏字段,Undo-log日志和ReadView三个东西实现。

隐藏字段:

主要有DB_ROW_ID、DB_Deleted_Bit、DB_TRX_ID、DB_ROLL_PTR这四个隐藏字段
隐藏主键-RowID(隐式):聚簇索引没有指定主键会选取一个合适的作为主键或者生成,也就是这个主键。底层存储需要构建树。

没有主键选取规则:1自增键位,2非空字段,3创建一个递增的Row_ID作为聚簇索引列

删除标识-Deleted_Bit:先设置为1,用于标识有事务将该条数据标识为delete了,其他sql不会将这条数据作为结果。如果事务成功则等待purger来进行删除,如果事务失败回滚,设置为0就好。用这个机制的优点在于,不用真正再索引中删除,使得树结构改变。优势如下:

  • 不用删除表数据,不会破坏树结构
  • 事务回滚,不用再插入数据。

purger删除机制,在设置了删除标识为1后,会自动删除缓存树,防止占用过多的磁盘,purger自身维护了一个ReadView。

最近更新的事务ID-TRX_ID(6Byte):对于每一个创建的事务都会有一个事务ID,事务ID递增,除了查询的事务ID=0,用于记录事务的ID
**回滚指针-ROLL_PTR(7Bytes)😗*每个事务都会有一个回滚指针,老版本的数据在Undo-log中,rollback_pointer就是地址指针,指向undo-log中的旧版本的数据。需要回滚事务就需要用到这个隐藏列。

undo-log日志:

undo-log记录了旧版本的数据,这个是一个版本链,不止一个版本的数据,只要有修改操作就会被记录,串起来的版本链,最新的旧数据在链表头。版本链就是多版本。
image.png

对update语句举例:
1.先在数据上加排他锁,2.然后数据拷贝到undo-log,然后数据修改.3设置trx_id为当前事务ID,4.更新隐藏字段的roll_ptr,然后提交事务释放锁。

ReadView:

mysql为查询线程分配的事务ID是0,
就是一个事务读取一条数据时,MVCC对Mysql的运行状态生成一个快照,就是ReadView,包含了所有活跃事务的ID,一个select事务开始后,就会生成一个ReadView,包含四个部分:

  • create_trx_id:ReadView的事务ID
  • trx_ids[]:生成当前Read_View时,系统活跃的事务的ID列表。
  • up_limit_id:活跃事务列表中最小的ID
  • low_limit_id:生成当前Read_View时,系统分配的下一个事务ID。4a7bdb03908c4c95850e3efa0d18e599~tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

实现原理-运行原理:

  • 事务进行修改操作,将旧数据放入Undo-log日志中。
  • 事务进行查询操作,MVCC会生成一个ReadView快照。

undo-log主要存储数据的历史版本,ReadView主要进行多版本并发控制。

①当事务中出现select语句时,会先根据MySQL的当前情况生成一个ReadView。
_②判断行数据中的隐藏列trx_id与ReadView.creator_trx_id是否相同: _

  • 相同:代表创建ReadView和修改行数据的事务是同一个,自然可以读取最新版数据。
  • 不相同:代表目前要查询的数据,是被其他事务修改过的,继续往下执行。

_③判断隐藏列trx_id是否小于ReadView.up_limit_id最小活跃事务ID: _

  • 小于:代表改动行数据的事务在创建快照前就已结束,可以读取最新版本的数据。
  • 不小于:则代表改动行数据的事务还在执行,因此需要继续往下判断。

_④判断隐藏列trx_id是否小于ReadView.low_limit_id这个值: _

  • 大于或等于:代表改动行数据的事务是生成快照后才开启的,因此不能访问最新版数据。
  • 小于:表示改动行数据的事务ID在up_limit_id、low_limit_id之间,需要进一步判断。

_⑤如果隐藏列trx_id小于low_limit_id,继续判断trx_id是否在trx_ids中: _

  • 在:表示改动行数据的事务目前依旧在执行,不能访问最新版数据。
  • 不在:表示改动行数据的事务已经结束,可以访问最新版的数据。

就是首先会去获取表中行数据的隐藏列,然后经过上述一系列判断后,可以得知:目前查询数据的事务到底能不能访问最新版的数据。如果能,就直接拿到表中的数据并返回,反之,不能则去Undo-log日志中获取旧版本的数据返回。如果Undo-log日志中的旧数据存在一个版本链时,此时会首先根据隐藏列roll_ptr找到链表头,然后依次遍历整个列表,从而检索最合适的一条数据并返回。

  • 隐藏列trx_id不能在ReadView.trx_ids中,因为数据旧数据不能读取。因为还没有提交。

select查询到新添加的数据,这时候roll_ptr=null,不会读取到这条数据。查询数据的事务不能读取最新版数据,同时又无法从版本链中找到旧数据,那就意味着这条数据对T1事务完全不可见,解决幻读

RC,RR不同级别下的MVCC机制:

MySQL的事务隔离机制处于
RC情况下,每次进行查询,都会生成readview
RR情况下,只进行第一次查询会生成ReadView就不会出现问题。
可以解决幻读

总结:

MVCC多版本并发控制,就是通过undo-log记录历史版本数据,然后通过隐藏字段+ReadView快照进行回滚和并发处理逻辑。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQLMVCC(Multi-Version Concurrency Control)机制是一种并发控制机制,用于处理并发事务的读写冲突。它通过为每个事务创建一个独立的版本,并使用这些版本来提供对数据的一致性读取,从而实现并发控制。 MVCC机制MySQL中的实现主要依赖于以下两个重要的组件: 1. Undo日志:MySQL使用undo日志记录数据修改操作的旧值。当一个事务开始时,MySQL会将当前数据行的快照复制到undo日志中。如果其他事务需要读取该数据行,它将读取这个快照而不受正在进行的事务的影响。 2. Read View:Read View是一个事务的快照视图,用于确定哪些数据行是对当前事务可见的。每个事务在开始时都会创建一个Read View。Read View包含一个活动事务列表和一个已提交事务列表。活动事务列表包含当前正在运行的活动事务,已提交事务列表包含已经提交的事务。当一个事务需要读取数据时,它会根据Read View确定哪些数据行是可见的。 基于这两个组件,MVCC机制提供了以下几个特点: 1. 高并发性:MVCC机制允许多个事务并发地读取和修改数据,因为它们之间不会产生读写冲突。 2. 一致性读取:MVCC机制确保事务只能读取已经提交的数据,避免了脏读和不可重复读的问题。 3. 无锁读取:MVCC机制的读取操作不会阻塞写入操作。读取操作只需要根据Read View判断数据是否可见。 需要注意的是,MVCC机制只适用于InnoDB存储引擎,而不适用于其他存储引擎,如MyISAM。另外,MVCC机制在一些特殊情况下可能会导致存储空间的增加,因为每个事务都会创建一个版本。因此,在设计数据库时需要考虑这些因素。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值