首页 > 编程知识 正文

mvcc多版本并发控制,cmf设计分析

时间:2023-05-06 17:51:24 阅读:166631 作者:2699

同时读写数据库时,读取操作可能不一致的数据(脏读)。 要避免这种情况,必须实现数据库的并发访问控制。 最简单的方法是锁定访问。 锁定会导致读写序列化,从而导致不一致。 但是,读取操作会被写入操作阻止,读取性能会大幅降低。 java concurrent包包含特定于优化读远大于写的copyonwrite系列类。 其优化手段是在进行写入操作时,将数据copy一份不影响原始数据,然后进行修改,修改完成后原子替换旧数据,读取操作只读取原始数据。 通过这样实现写入动作,读取动作不会被阻塞,读取效率得以优化。 另一方面,写入是互斥的,每次写入都会发生复制,因此仅适用于读取比写入大的情况。

MVCC的原理与copyonwrite类似,全名是多版本并发控制。 MVCC协议为每个读取操作提供一致的快照,从而实现无阻塞的读取。 在MVCC中,数据可以包含多个版本。 此版本是时间戳或全局递增的事务ID,在同一时刻不同的事务显示的数据不同。

实现原理:

请参见----------------------------------------- -

|--------r(T1 )-----|

|---------u (T2 )-----|

在上图中,假设r(T1 )和u ) T2 )有两个并发操作。 T1和T2是事务ID,T1小于T2,系统中包含的数据a=1) T1 ),r和w的操作如下:

r :读我(t1 ) )。

u:a=2(T2 ) ) )。

r (读取操作)的版本T1表示要读取的数据的版本,在进行写入操作之前不更新版本,不进行读取操作。 在时间轴上,r比u慢,u在r开始后提交,因此对r来说是不可见的。 因此,r只读取T1版本的数据,即a=1。

在提交update操作之前,无法影响现有数据的完整性,因此旧数据不会更改,update操作将被拆分为插入删除。 必须标记删除旧数据,然后插入新数据。 在update提交之前,不会影响后续的读取操作。 此外,读取操作只能读取以前的所有写入操作,而无法看到正在执行的写入操作。

上面阐述了很多空洞的理论,让我们来看看mysql的innodb引擎是如何实现MVCC的。 innodb在每行中添加两个表示创建的版本删除的版本的字段,并输入事务的版本号。 此版本号会随着事务的创建而增加。 在repeated read的隔离级别(事务的隔离级别见本文)下,实现各种具体的数据库操作:

select :如果满足以下两个条件,innodb将返回此行中的数据: (1)该行的创建版本号小于或等于当前版本号,用于确保在select操作之前所有操作均已落地。 )2)该行的删除版本号大于当前版本或为空。 版本号大于当前版本意味着存在要删除行的并发事务。

insert将新插入行的创建版本号设置为当前系统的版本号。

删除将要删除的行的删除版本号设置为当前系统的版本号。

update :不执行当时的update,转换为insert delete。 将旧行的删除版本号设置为当前版本号,在新行的insert中将创建版本号设置为当前版本号。

在此,执行写入(insert、delete、update )时,需要使系统的版本号递增。

旧数据实际上不会被删除,因此需要清理这些数据。 innodb将打开后台线程以执行清理工作。 具体规则是删除版本号小于当前系统版本的行。 这个过程称为purge。

MVCC可以很好地实现事务隔离,并达到“已读”级别。 要实现可串行化,必须上锁。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。