MVCC浅析
【转载】http://blog.csdn.net/chosen0ne/article/details/18093187
在并发读写数据库时,读操作可能会不一致的数据(脏读)。为了避免这种情况,需要实现数据库的并发访问控制,最简单的方式就是加锁访问。由于,加锁会将读写操作串行化,所以不会出现不一致的状态。但是,读操作会被写操作阻塞,大幅降低读性能。在java concurrent包中,有copyonwrite系列的类,专门用于优化读远大于写的情况。而其优化的手段就是,在进行写操作时,将数据copy一份,不会影响原有数据,然后进行修改,修改完成后原子替换掉旧的数据,而读操作只会读取原有数据。通过这种方式实现写操作不会阻塞读操作,从而优化读效率。而写操作之间是要互斥的,并且每次写操作都会有一次copy,所以只适合读大于写的情况。
MVCC的原理与copyonwrite类似,全称是Multi-Version Concurrent Control,即多版本并发控制。在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。
实现原理:
------------------------------------------------------------------------------------------> 时间轴
|-------R(T1)-----|
|-----------U(T2)-----------|
如上图,假设有两个并发操作R(T1)和U(T2),T1和T2是事务ID,T1小于T2,系统中包含数据a = 1(T1),R和W的操作如下:
R:read a (T1)
U:a = 2 (T2)
R(读操作)的版本T1表示要读取数据的版本,而之后写操作才会更新版本,读操作不会。在时间轴上,R晚于U,而由于U在R开始之后提交,所以对于R是不可见的。所以,R只会读取T1版本的数据,即a = 1。
由于在update操作提交之前,不能影响已有数据的一致性,所以不会改变旧的数据,update操作会被拆分成insert + delete。需要标记删除旧的数据,insert新的数据。只有update提交之后,才会影响后续的读操作。而对于读操作而且,只能读到在其之前的所有的写操作,正在执行中的写操作对其是不可见的。
上面说了一堆的虚的理论,下面来点干活,看一下mysql的innodb引擎是如何实现MVCC的。innodb会为每一行添加两个字段,分别表示该行创建的版本和删除的版本,填入的是事务的版本号,这个版本号随着事务的创建不断递增。在repeated read的隔离级别(事务的隔离级别请看这篇文章)下,具体各种数据库操作的实现:
select:满足以下两个条件innodb会返回该行数据:(1)该行的创建版本号小于等于当前版本号,用于保证在select操作之前所有的操作已经执行落地。(2)该行的删除版本号大于当前版本或者为空。删除版本号大于当前版本意味着有一个并发事务将该行删除了。
insert:将新插入的行的创建版本号设置为当前系统的版本号。
delete:将要删除的行的删除版本号设置为当前系统的版本号。
update:不执行原地update,而是转换成insert + delete。将旧行的删除版本号设置为当前版本号,并将新行insert同时设置创建版本号为当前版本号。
其中,写操作(insert、delete和update)执行时,需要将系统版本号递增。
由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。
通过MVCC很好的实现了事务的隔离性,可以达到repeated read级别,要实现serializable还必须加锁。
转载请注明出处:http://www.mingweiauto.com/article/20230526/682224.html
随机推荐
-
在ASP.NET MVC C#中连接到多个表或联接两个表
如果标题令人困惑,很抱歉。假设我有一个名为Employee的模型。Employee有一个名为Departments的列。这允许他们查看该部门的日历。但是有些员工应该能够查看多个部门的日历,而且每个员工的日历都是不同的。因为有许多不同的部门,...
-
三分钟图解 MVCC,看一遍就懂
前文我们介绍了 InnoDB 存储引擎在事务隔离级别 READ COMMITTED 和 REPEATABLE READ(默认)下会开启一致性非锁定读,简单回顾下:所谓一致性非锁定读就是每行记录可能存在多个历史版本,多版本之间串联起来形成了...
-
MVCC - Read View的可见性判断理解
读了 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 收益颇丰,非常感谢! 但对其中如何判断事务是否可见性还是不太理解,于是作了本文,在原博客基础上,举例画图论证、理解了Read View的可见性判断。...
-
浅析MySQL - MVCC
版本链 在InnoDB引擎表中,他们的聚簇索引记录中有两个隐藏列: trx_id:用来存储对数据进行修改时的事务id roll_pointer:每次对哪条聚簇索引记录有修改的时候,就会把老版本写入undo日志中。这个roll_p...
-
Mysql MVCC机制原理详解
目录什么是MVCC Mysql的锁和事务隔离级别 Mysql的undo log MVCC的实现原理 什么是MVCC MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发...
-
ASP.NET MVC C#:将视图数据传递给控制器
查看未传递给控制器的数据。请注意,我使用的是实体框架。尝试设置Jobcard的值,以便我可以保存它们,但字段未绑定到模型。请帮助我解决这个问题,任何帮助都将不胜感激。查看Cshtml@model Amax.Models.Jobcard @...
-
MVCC原理
MVCC MVCC (Multi-Version Concurrency Control) ,即多版本并发控制,利用记录的版本链和ReadView,来控制并发事务访问相同记录时的行为。ReadView即一致性视图,用来判断版本链中的哪...
-
PostgreSQL MVCC原理以及事务可见性对执行计划的影响
先从上次遇到的一个执行计划相关的疑问入手,类似于select count(1) from table的查询,可以在即某些较小字段上的索引进行扫描来替代全表扫描来实现count优化,这是一个MySQL中传统的优化套路,但是在postgre...
-
文件上传MVC c#后重定向返回错误行和消息
我在HTML页面上有一个importFile按钮,点击导入文件,处理文件,如果有任何错误,返回一个消息“文件上传失败与错误。请检查下载的错误文件”。如果没有错误,则只显示File uploaded“消息。这是我的视图: @using (Ht...
-
MySql MVCC是如何实现的-关于autocommit?
关于autocommit 查看autocommit show variables like 'autocommit'; mysql show variables like 'autocommit'; +--------------...