您的位置:首页 > 科技 > 能源 > 平台公司市场化运营_西安旅游攻略_诊断网站seo现状的方法_线上宣传有哪些好的方式方法

平台公司市场化运营_西安旅游攻略_诊断网站seo现状的方法_线上宣传有哪些好的方式方法

2025/1/10 20:00:42 来源:https://blog.csdn.net/weixin_43390123/article/details/143321183  浏览:    关键词:平台公司市场化运营_西安旅游攻略_诊断网站seo现状的方法_线上宣传有哪些好的方式方法
平台公司市场化运营_西安旅游攻略_诊断网站seo现状的方法_线上宣传有哪些好的方式方法

这里写自定义目录标题

  • 为什么要有MVCC?
    • 如何实现?
    • Read View以及可重复读的隔离原理
    • 读已提交是如何实现的?
    • 总结

为什么要有MVCC?

从用户需求出发,数据库想要实现什么功能呢?事务想要实现隔离性,也就是如果多个事务同时运行,各个事务之间不能相互打扰(不能有脏读、不可重复读、幻读)。其实加锁可以简单粗暴的解决这个问题,但如果连读操作都频繁加锁,显然会严重影响效率,因此如何在不加锁的情况下解决多个事务的并发读问题,是多版本并发控制(MVCC)实现的出发点。

如何实现?

现在我们有很多个事务,它们面对着同一张表,表里有很多条数据。有的事务可能在修改某条记录,有的在查询,有的在删除。如何让每个事务只能看到自己应该看到的数据呢?

首先我们想到,应该给每个事务编号,并且这个编号和每一行数据有一个对应关系,这样才能控制某个事务只能看某些数据。因此,INNODB在每行记录中存放了一个隐藏字段trx_id即最近一次插入或更新这条记录的事务id。

然后,每个事务应该知道自己当前能看哪些事务的数据,这里就要区分事务的隔离级别了,读已提交显然要比可重复读能看到的数据多一些。Mysql 通过Read View来记录创建一个事务时,系统中其他事务的相关信息,并以此来判断当前事务对某条数据的可见性。

Read View以及可重复读的隔离原理

顾名思义,Read View 就是个“读视图”,或者说事务在创建时“拍了个快照”。如果类比java的数据结构的话,可以把它看做事务中的一部分,一个内部类。

class ReadView {trx_id[] m_ids; //表示在生成readview时,当前系统中活跃的读写事务id数组; trx_id min_trx_id; /*表示在生成readview时,当前系统中活跃的读写事务中最小的事务id,也就是m_ids中最小的值,低水位; */trx_id max_trx_id; //表示生成readview时,系统中应该分配给下一个事务的id值,高水位; trx_id creator_trx_id; //表示生成该readview的事务的事务id;
}

以上代码并不是真实的实现哈,只是为了方便理解,临时编写的一个类。
我们先以可重复读隔离级别为例,在Repeatable Read隔离级别下,Mysql将在启动事务时创建一个Read View,因此事务后续在访问数据记录时会有以下几种情况:

  • 如果记录的 trx_id 值等于Read View中的creator_trx_id,也就是说这条记录就是当前事务创建的,显然该记录可见;
  • 如果记录的 trx_id 值小于Read View中的min_trx_id,表示该版本的记录在本事务创建之前就有了,因此可见;
  • 如果记录的 trx_id 值大于Read View中的max_trx_id,表示该版本的记录在本事务创建之后才创建,因此不可见;
  • 如果记录的 trx_id 值介于min_trx_id和max_trx_id之间,就要进一步判断trx_id是否在数组m_ids中:
    • 如果trx_id在数组m_ids中,表明生成该记录的事务还没提交,处于活跃状态,因此该记录对当前事务不可见;
    • 如果trx_id不在数组m_ids中,表明生成该记录的事务已经被提交,因此该记录可见。

这时还有一个问题,就是某条数据因为事务状态的原因导致不可见,但是这条数据之前就存在了,也就是说当前事务应该看到这条数据之前的版本,这应该如何实现呢?
mysql记录存储示意图
其实,在mysql的数据行中还有一个隐藏列,就是roll_pointer,每次事务对记录创建或修改时,都会将旧版本的数据计入undo日志,roll_pointer则负责以指针的形式连接这些不同版本的数据。当一个版本的trx_id不可见时,会顺着roll_pointer向以前的版本寻找,直到数据可见或没有数据。

读已提交是如何实现的?

上面描述了可重复读的工作原理,那读已提交是如何实现的呢?其实它俩的区别就一句话:

可重复读只在事务开始时创建一次Read View,读已提交会在每次读操作时创建Read View。

这就意味着,在可重复读隔离级别下,如果事务A在执行过程中,其他事务提交了数据,A相当于是完全不知道的,它将会读到事务开始时的数据;而在读已提交隔离级别下,每次读操作都会刷新Read View,里面的各项参数也随之被更新,其他事务提交的修改就可见了。

总结

本文主要介绍了MVCC的工作原理,以及数据中的隐藏列和Read View是如何配合的。需要注意的是,MVCC只解决了快照读的隔离问题(也就是普通的select语句),这对于读已提交隔离级别来说已经足够,因为当前读和快照读的表现是一样的。而对于可重复读隔离级别来说,当前读还会产生幻读和不可重复读现象,这需要加锁解决,该问题将在后续文章中阐述。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com