Mysql中的MVCC
mysql mvcc多版本并发控制的原理

mysql mvcc多版本并发控制的原理MySQL是最流行的开源关系型数据库管理系统之一。
支持多版本并发控制(MVCC),以实现高并发性和事务一致性。
本文将详细讲解MySQL MVCC的原理。
1. 事务和锁由于MySQL是多用户环境下的数据库系统,因此并发事务的支持至关重要。
MySQL使用锁机制来确保在并发环境下事务的一致性。
当一个事务要访问某个数据库对象时,它需要在该对象上获取锁。
这种锁的类型有两种:共享锁和排他锁。
共享锁适用于读取操作,它可以被多个事务同时持有。
而排他锁适用于写入操作,它只能被一个事务持有。
当事务需要修改某个对象时,它必须先获取排他锁。
如果该对象被其他事务持有共享锁,则此时该事务需要等待所有共享锁释放后才能获取该对象的排他锁。
这种等待时间可能会导致一定的性能问题,因此MySQL采用了MVCC机制来优化并发性能。
2. MVCC的原理MVCC是指多版本并发控制,是MySQL提高并发性能和事务一致性的一种机制。
当一个事务查询某个数据库对象时,它会查找该对象的历史版本并返回给用户。
这种历史版本的生成是通过在修改数据库对象时产生的。
每当有一个事务修改某个数据库对象时,系统会将原有版本的对象复制一份,并在新版本上执行修改操作,这样就生成了一个新版本的对象。
新版本的对象包含了上一个版本的数据以及新的修改操作。
这样就形成了一条对象历史版本链。
当事务读取某个数据库对象时,系统会在历史版本链中查找满足读取条件的最新版本。
如果该版本的对象被其他事务持有排他锁,则读取操作会失败。
如果该版本的对象被其他事务持有共享锁,则读取操作仍然可以成功。
这样就避免了读操作之间的等待时间,提高了数据库的并发性能。
当事务修改某个数据库对象时,系统会创建一个新的版本,并把该新版本设置为当前版本。
这个过程涉及到一些复杂的技术细节,但基本的原理不会改变。
3. MVCC的局限性MVCC机制可以优化查询性能,但由于每个版本的对象需要占用一定的存储空间,因此可能会增加存储开销。
MySQL-acid-mvcc以及=事物隔离级别

MySQL --- acidA:原子性> 保证一个事务为一个最小的单元,内部不可分割。
C:一致性> 保证事务中的每个操作线程不可单独提交,成功则一起提交,不成功则事务回滚;I : 隔离性> 保证不同事务间看到的数据视图相互独立,相互隔离。
[ 提交读(read committed)和repeatable read(默认)] 这两个事物隔离级别的差别,就是当一个事物开始的时候,始终读取的信息是开始事物的那一刻的数据快照。
这样的级别叫repeatable read,提交读就撒始终读取的是最近的数据。
其他两个隔离叫未提交读(READ UNCOMMITTED) 和SERIALIZABLE(可串行化) 用的非常少,其中可串行化这个还使用其他的NoSQL队列来代替。
D:持久性> 保证事务提交后数据会持久的保存下来.Mysql的事务存储引擎Innodb 加锁机制叫多版本并发控制(MVCC)技术以便应对更高的并发,当然是以消耗性能作为代价。
简单实现方式如下:InnoDB实现MVCC的方法是,它存储了每一行的两个(1)额外的隐藏字段,这两个隐藏字段分别记录了行的创建的时间和删除的时间。
在每个事件发生的时候,每行存储版本号,而不是存储事件实际发生的时间。
每次事物的开始这个版本号都会增加。
自记录时间开始,每个事物都会保存记录的系统版本号。
依照事物的版本来检查每行的版本号。
在事物隔离级别为可重复读的情况下,来看看怎样应用它。
SELECTInnodb检查没行数据,确保他们符合两个标准:1、InnoDB只查找版本早于当前事务版本的数据行(也就是数据行的版本必须小于等于事务的版本),这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行2、行的删除操作的版本一定是未定义的或者大于当前事务的版本号。
确定了当前事务开始之前,行没有被删除(2)符合了以上两点则返回查询结果。
INSERTInnoDB为每个新增行记录当前系统版本号作为创建ID。
mvcc多版本并发控制的原理

mvcc多版本并发控制的原理多版本并发控制(MVCC)是一种数据库并发控制技术,用于在多用户同时访问数据库时确保事务的一致性和隔离性。
MVCC技术在许多常见的数据库系统中都得到了广泛的应用,比如PostgreSQL、MySQL 和Oracle等。
本文将介绍MVCC技术的原理及其在数据库系统中的应用。
1. MVCC技术的原理MVCC技术的核心原理是基于对数据的多个版本进行管理。
它通过在数据库中维护数据的多个版本来实现并发控制,从而避免了传统的锁定机制所带来的性能问题。
在MVCC中,每个事务可以看到一个数据的特定版本,而不需要等待其他事务的提交或者回滚。
MVCC技术的实现依赖于以下几个关键组件:-版本号:每个数据行都有一个对应的版本号,用于标识该数据的版本。
当一个事务对数据进行修改时,数据库会为其生成一个新的版本号。
-可见性控制:数据库系统使用版本号来判断一个事务是否可以看到某个数据的版本。
当一个事务开始时,数据库会为该事务定义一个可见性范围,只有在该范围内生成的数据版本才可以被该事务看到。
在MVCC技术中,数据的修改不会直接覆盖原始数据,而是生成一个新的版本。
这样做的好处是可以避免对原始数据的修改,从而减少了数据的冲突和锁定。
当一个事务需要对数据行进行修改时,MVCC会为其生成一个新的数据版本,并更新事务的可见性范围,从而保证事务之间的隔离性。
2. MVCC技术在数据库系统中的应用MVCC技术在数据库系统中的应用非常广泛,尤其是在需要高并发访问的场景下。
下面我们将介绍MVCC技术在一些常见数据库系统中的应用。
(1) PostgreSQLPostgreSQL是一个开源的关系型数据库系统,在其内部实现了MVCC技术。
PostgreSQL使用了基于快照的多版本并发控制机制,它通过为每个事务分配唯一的事务ID来实现可见性的控制。
当一个事务对数据进行修改时,PostgreSQL会为其生成一个新的数据版本,并将旧的版本标记为无效,从而保证了事务之间的隔离性。
mysqlmvcc实现原理

mysqlmvcc实现原理
MySQL的MVCC是指多版本并发控制,是一种数据库并发控制技术,用于提供高并发操作数据库时的隔离性。
MySQL的MVCC技术实现原理如下:
MySQL中每条记录都有一个版本号,版本号会随着事务的执行而不断变化。
当一个事务开始执行时,MySQL会将当前记录复制一份,并对该复制出来的记录进行修改,而不是对原记录进行修改。
该复制出来的记录版本号与原记录版本号相等,随着事务的执行,记录版本号会递增。
当一个事务执行SELECT语句时,它会读取当前记录的版本号,如果该版本号小于等于事务的开始时间,则该记录对该事务可见。
不可见的记录则被忽略。
当一个事务执行INSERT、UPDATE、DELETE语句时,MySQL会为新的记录生成一个新的版本号,并将新的版本号和修改后的记录一起写入磁盘。
但是,原记录版本号不会更改,因此,其他正在执行的事务依然可以读取原记录。
当一个事务执行COMMIT语句时,MySQL会将该事务操作写入磁盘,同时会将该事务开始时的所有记录版本号写入Undo日志。
如果该事务执行ROLLBACK操作,MySQL会将该事务开始时的所有记录版本号在Undo日志中进行回滚。
通过该机制,MySQL实现了高并发操作下的隔离性,避免了数据的混乱和操作的冲突。
数据库mvcc实现原理

数据库mvcc实现原理MVCC(Multi-Version Concurrency Control)是一种并发控制的技术,在数据库系统中用于处理并发事务对数据的读写操作。
MVCC的原理是在每个数据行中维护多个版本,每个版本都有一个时间戳。
当一个事务开始时,数据库系统会为该事务分配一个唯一的时间戳。
在读取数据时,事务只能看到在该事务开始之前或者已经提交的数据版本。
在写入数据时,如果该数据行已经存在一个更新的版本(即时间戳较大的版本),系统会创建一个新的版本,并将该版本的引用更新到事务的修改列表中。
这样就保证了事务读取的是一个一致性的数据版本,并且不会受到其他并发事务的影响。
MVCC的实现主要涉及以下几个方面:1. 为每个数据行添加版本信息:数据库系统会为每个数据行添加一个或多个版本,每个版本都包含时间戳等信息。
2. 事务的时间戳分配:每个事务开始时,数据库系统会为该事务分配一个唯一的时间戳,用于决定该事务能够读取的数据版本范围。
3. 读操作的处理:在读取数据时,事务只能读取在该事务开始之前或已经提交的数据版本。
数据库系统根据事务的时间戳和数据版本的时间戳进行比较,来确定可见的数据版本。
4. 写操作的处理:当一个事务对数据进行修改时,如果该数据行已经存在一个更新的版本,则系统会创建一个新的版本,并将该版本的引用更新到事务的修改列表中。
同时,系统还会为该事务分配一个唯一的时间戳作为新版本的时间戳。
5. 数据清理:为了释放存储空间并提高性能,系统会定期清理过期的数据版本。
过期的数据版本是指已经被其他事务所看不见的版本。
通过使用MVCC,数据库系统可以实现高度的并发性和一致性。
不同事务之间的读写操作可以同时进行,而且事务之间不会相互阻塞。
同时,MVCC还能够提供历史读功能,即事务可以读取到过去某个时间点的数据版本,从而满足一些特殊的需求。
innodb的mvcc实现原理

innodb的mvcc实现原理
InnoDB是MySQL的一种存储引擎,支持多版本并发控制(MVCC)。
MVCC是指在一个事务中,不同的操作可以看到不同的数据版本,使得多个并发的事务可以同时访问同一个数据,而不会相互干扰。
InnoDB的MVCC实现主要包括以下几个方面:
1. 版本号:每个事务在修改数据时都会为数据新增一个版本号,表示该数据的修改时间。
而读取数据时,根据事务的启动时间和版本号的大小判断当前可见的数据版本。
2. 事务ID:每个事务都有一个唯一的ID,用于标识该事务。
在读取数据时,根据事务ID和版本号的大小判断当前可见的数据版本。
3. Undo日志:每个事务在修改数据时,都会生成一个Undo日志,记录修改前的数据和修改后的数据信息。
如果事务回滚,则可以根据Undo日志还原修改前的数据。
4. Purge:InnoDB会定期清理已经不再需要的Undo日志,释放空间。
通过这些机制,InnoDB实现了MVCC,在高并发的情况下保证了数据的正确性和一致性。
但同时也会带来一定的性能消耗,因为每个事务都要维护版本号和Undo日志。
因此,在实际使用中需要根据具体情况进行权衡和优化。
- 1 -。
mvcc工作原理
mvcc工作原理
MVCC(Multi-VersionConcurrencyControl)是一种常用于数据库管理系统中的并发控制技术。
它的主要目的是允许多个用户同时访问数据库,而不会导致数据冲突和不一致性。
MVCC通过在系统中维护多个版本的数据来实现这一目的。
MVCC工作原理如下:
1.每个事务都会启动时,系统会为其分配一个唯一的事务ID
2.当一个事务要访问数据库中的某个数据时,系统会检查该数据的版本号和事务的启动时间,如果该数据的版本号早于该事务的启动时间,则该事务可以访问该数据;否则,该事务需要等待其他事务完成对该数据的访问。
3.当一个事务修改某个数据时,系统会为该数据创建一个新版本号,并将修改后的数据存储在一个新的位置。
同时,旧版本的数据仍然可用供其他事务访问。
4.当一个事务提交时,系统会将其所做的所有修改操作都合并到数据库中,同时删除旧版本的数据。
MVCC的优点是可以提高并发访问数据库的效率,并减少数据冲突和不一致性的发生。
同时,MVCC也可以提供更高级别的隔离性,确保每个事务的结果与其他事务的结果相互独立。
总之,MVCC是一种非常重要的并发控制技术,它的工作原理可以帮助我们更好地理解数据库管理系统的运作方式。
- 1 -。
MySQL的MVCC机制,详细解答
MySQL的MVCC机制,详细解答⽬录1、MVCC简介1.1 MVCC是什么?MVCC,Multi-Version Concurrency Control,多版本并发控制。
MVCC 是⼀种并发控制的⽅法,⼀般在数据库管理系统中,实现对数据库的并发访问;1.2 MVCC是为了解决什么?⼤多数的MYSQL事务型存储引擎,如,InnoDB,Falcon以及PBXT都不使⽤⼀种简单的⾏锁机制.事实上,他们都和MVCC–多版本并发控制来⼀起使⽤⼤家都应该知道,锁机制可以控制并发操作,但是其系统开销较⼤,⽽MVCC可以在⼤多数情况下代替⾏级锁,使⽤MVCC,能降低其系统开销 众所周知,在MYSQL中,MyISAM使⽤的是表锁,InnoDB使⽤的是⾏锁。
⽽InnoDB的事务分为四个隔离级别,其中默认的隔离级别REPEATABLE READ需要两个不同的事务相互之间不能影响,⽽且还能⽀持并发,这点悲观锁是达不到的,所以REPEATABLE READ采⽤的就是乐观锁,⽽乐观锁的实现采⽤的就是MVCC。
正是因为有了MVCC,才造就了InnoDB强⼤的事务处理能⼒。
MVCC解决的问题是读写互相不阻塞的问题,每次更新都产⽣⼀个新的版本,读的话可以读历史版本。
试想,如果⼀个数据只有⼀个版本,那么多个事务对这个数据进⾏读写是不是需要读写锁来保护?⼀个读写事务在运⾏的过程中在访问数据之前先加读/写锁这种实现叫做悲观锁,悲观体现在,先加锁,独占数据,防⽌别⼈加锁。
乐观锁呢,读写事务,在真正的提交之前,不加读/写锁,⽽是先看⼀下数据的版本/时间戳,等到真正提交的时候再看⼀下版本/时间戳,如果两次相同,说明别⼈期间没有对数据进⾏过修改,那么就可以放⼼提交。
乐观体现在,访问数据时不提前加锁。
在资源冲突不激烈的场合,⽤乐观锁性能较好。
如果资源冲突严重,乐观锁的实现会导致事务提交的时候经常看到别⼈在他之前已经修改了数据,然后要进⾏回滚或者重试,还不如⼀上来就加锁。
MysqlMVCC机制原理详解
MysqlMVCC机制原理详解⽬录什么是MVCCMysql的锁和事务隔离级别Mysql的undo logMVCC的实现原理什么是MVCCMVCC,全称Multi-Version Concurrency Control,即多版本并发控制。
MVCC是⼀种并发控制的⽅法,⼀般在数据库管理系统中,实现对数据库的并发访问,在编程语⾔中实现事务内存。
我们知道,⼀般情况下我们使⽤mysql数据库的时候使⽤的是Innodb存储引擎,Innodb存储引擎是⽀持事务的,那么当多线程同时执⾏事务的时候,可能会出现并发问题。
这个时候需要⼀个能够控制并发的⽅法,MVCC就起到了这个作⽤。
Mysql的锁和事务隔离级别在理解MVCC机制的原理之前,需要先理解Mysql的锁机制和事务的隔离级别,抛开MyISAM存储引擎不谈,就Innodb存储引擎来说,分别有⾏锁和表锁两种锁,表锁就是⼀次操作锁住整张表,这样锁的粒度最⼤,但是性能也最低,不会出现死锁。
⾏锁就是⼀次操作锁住⼀⾏,这样锁的粒度⼩,并发度⾼,但是会出现死锁。
Innodb的⾏锁⼜分为共享锁(读锁)和排它锁(写锁),当⼀个事务对某⼀⾏加了读锁时,允许其他事务对这⼀⾏进⾏读操作,但是不允许进⾏写操作,也不允许其他事务对这⼀⾏执⾏加写锁,但是可以加读锁。
当⼀个事务对某⼀⾏加了写锁时,不允许其他事务对这⼀⾏进⾏写操作,但是可以读,同时不允许其他事务对这⼀⾏加读写锁。
下⾯来看⼀下Mysql的事务隔离级别,分为以下四种:1. 读未提交:⼀个事务可以读到其他事务还没有提交的数据,会出现脏读。
举个例⼦,有⼀张⼯资表,事务A先开启,然后执⾏查询id为1的员⼯的⼯资,假设此时的⼯资为1000,此时,事务B也开启,执⾏了更新操作,将id为1的员⼯⼯资减少了100,但是并未提交事务。
此时再执⾏事务A的查询操作,可以读到事务B已经更新的数据,如果此时事务B发⽣回滚,事务A读到的就是“脏”数据。
当事务A执⾏更新操作的话还可能产⽣幻读的情况。
MySQL的多版本并发控制与MVCC原理
MySQL的多版本并发控制与MVCC原理MySQL是一种常用的开源关系型数据库管理系统,被广泛应用于互联网应用和企业级系统中。
MySQL具备强大的并发能力,并且通过多版本并发控制(MVCC)机制来实现数据的一致性和隔离性。
本文将探讨MySQL的多版本并发控制原理以及MVCC的工作机制。
一、MySQL的并发问题在多用户同时操作数据库的情况下,数据库系统需要处理并发读写操作,以保证数据一致性和隔离性。
然而,传统的锁机制在高并发访问下存在很大的性能问题。
为了解决这个问题,MySQL引入了多版本并发控制(MVCC)机制。
二、多版本并发控制(MVCC)原理MVCC是一种并发控制方法,通过对数据添加时间戳或版本号来实现数据版本的管理。
每个事务的启动时间确定了它所能看到的数据版本。
对于每个读操作,MySQL会根据时间戳或版本号来选择合适的数据版本,以实现数据的隔离性。
1. 数据版本在MVCC中,每个数据行都会存储多个版本的数据。
当某个事务对数据进行修改时,MySQL会为该事务创建一个新的数据版本,并将该版本的时间戳或版本号记录在数据行中。
这样,其他正在执行的事务可以继续读取原始数据版本,而不受到新版本的影响。
2. 读操作对于读操作,MySQL会根据事务的启动时间戳或版本号来选择数据版本。
如果某个事务的启动时间早于数据版本的创建时间,则该事务可见该数据版本,即可读取。
否则,该事务只能读取早于它启动时间的数据版本。
3. 写操作对于写操作,MySQL会为每个事务创建一个新的数据版本,并将新版本的时间戳或版本号记录在数据行中。
同时,MySQL还会维护一个回滚段,用于事务的回滚操作。
当事务提交时,新版本的数据会取代旧版本,成为最新的数据版本。
如果其他事务正在读取该旧版本,则它们将继续读取旧版本的数据。
三、MVCC的优点MVCC机制为MySQL带来了以下几个优点:1. 提高并发性能由于MVCC不是通过加锁实现并发控制,而是通过创建多个数据版本来实现数据的隔离,因此可以支持更高的并发性能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Mysql中的MVCCMysql到底是怎么实现MVCC的?这个问题无数人都在问,但google中并无答案,本文尝试从Mysql源码中寻找答案。
在Mysql中MVCC是在Innodb存储引擎中得到支持的,Innodb为每行记录都实现了三个隐藏字段:∙6字节的事务ID(DB_TRX_ID)∙7字节的回滚指针(DB_ROLL_PTR)∙隐藏的ID6字节的事物ID用来标识该行所述的事务,7字节的回滚指针需要了解下Innodb的事务模型。
1. Innodb的事务相关概念为了支持事务,Innbodb引入了下面几个概念:∙redo logredo log就是保存执行的SQL语句到一个指定的Log文件,当Mysql执行recovery时重新执行redo log记录的SQL操作即可。
当客户端执行每条SQL(更新语句)时,redo log会被首先写入log buffer;当客户端执行COMMIT命令时,log buffer中的内容会被视情况刷新到磁盘。
redo log在磁盘上作为一个独立的文件存在,即Innodb的log文件。
∙undo log与redo log相反,undo log是为回滚而用,具体内容就是copy事务前的数据库内容(行)到undo buffer,在适合的时间把undo buffer中的内容刷新到磁盘。
undo buffer 与redo buffer一样,也是环形缓冲,但当缓冲满的时候,undo buffer中的内容会也会被刷新到磁盘;与redo log不同的是,磁盘上不存在单独的undo log文件,所有的undo log均存放在主ibd数据文件中(表空间),即使客户端设置了每表一个数据文件也是如此。
∙rollback segment回滚段这个概念来自Oracle的事物模型,在Innodb中,undo log被划分为多个段,具体某行的undo log就保存在某个段中,称为回滚段。
可以认为undo log和回滚段是同一意思。
∙锁Innodb提供了基于行的锁,如果行的数量非常大,则在高并发下锁的数量也可能会比较大,据Innodb文档说,Innodb对锁进行了空间有效优化,即使并发量高也不会导致内存耗尽。
对行的锁有分两种:排他锁、共享锁。
共享锁针对对,排他锁针对写,完全等同读写锁的概念。
如果某个事务在更新某行(排他锁),则其他事物无论是读还是写本行都必须等待;如果某个事物读某行(共享锁),则其他读的事物无需等待,而写事物则需等待。
通过共享锁,保证了多读之间的无等待性,但是锁的应用又依赖Mysql的事务隔离级别。
∙隔离级别隔离级别用来限制事务直接的交互程度,目前有几个工业标准:- READ_UNCOMMITTED:脏读- READ_COMMITTED:读提交- REPEATABLE_READ:重复读- SERIALIZABLE:串行化Innodb对四种类型都支持,脏读和串行化应用场景不多,读提交、重复读用的比较广泛,后面会介绍其实现方式。
2. 行的更新过程下面演示下事务对某行记录的更新过程:1. 初始数据行F1~F6是某行列的名字,1~6是其对应的数据。
后面三个隐含字段分别对应该行的事务号和回滚指针,假如这条数据是刚INSERT的,可以认为ID为1,其他两个字段为空。
2.事务1更改该行的各字段的值当事务1更改该行的值时,会进行如下操作:∙用排他锁锁定该行∙记录redo log∙把该行修改前的值Copy到undo log,即上图中下面的行∙修改当前行的值,填写事务编号,使回滚指针指向undo log中的修改前的行3.事务2修改该行的值与事务1相同,此时undo log,中有有两行记录,并且通过回滚指针连在一起。
因此,如果undo log一直不删除,则会通过当前记录的回滚指针回溯到该行创建时的初始内容,所幸的时在Innodb中存在purge线程,它会查询那些比现在最老的活动事务还早的undo log,并删除它们,从而保证undo log文件不至于无限增长。
4. 事务提交当事务正常提交时Innbod只需要更改事务状态为COMMIT即可,不需做其他额外的工作,而Rollback则稍微复杂点,需要根据当前回滚指针从undo log中找出事务修改前的版本,并恢复。
如果事务影响的行非常多,回滚则可能会变的效率不高,根据经验值没事务行数在1000~10000之间,Innodb效率还是非常高的。
很显然,Innodb是一个COMMIT效率比Rollback高的存储引擎。
据说,Postgress的实现恰好与此相反。
5. Insert Und o log上述过程确切地说是描述了UPDATE的事务过程,其实undo log分insert和update undo log,因为insert时,原始的数据并不存在,所以回滚时把insert undo log丢弃即可,而update undo log则必须遵守上述过程。
3. 事务级别众所周知地是更新(update、insert、delete)是一个事务过程,在Innodb中,查询也是一个事务,只读事务。
当读写事务并发访问同一行数据时,能读到什么样的内容则依赖事务级别:∙READ_UNCOMMITTED读未提交时,读事务直接读取主记录,无论更新事务是否完成∙READ_COMMITTED读提交时,读事务每次都读取undo log中最近的版本,因此两次对同一字段的读可能读到不同的数据(幻读),但能保证每次都读到最新的数据。
∙REPEATABLE_READ每次都读取指定的版本,这样保证不会产生幻读,但可能读不到最新的数据∙SERIALIZABLE锁表,读写相互阻塞,使用较少读事务一般有SELECT语句触发,在Innodb中保证其非阻塞,但带FOR UPDATE的SELECT 除外,带FOR UPDATE的SELECT会对行加排他锁,等待更新事务完成后读取其最新内容。
就整个Innodb的设计目标来说,就是提供高效的、非阻塞的查询操作。
4. MVCC上述更新前建立undo log,根据各种策略读取时非阻塞就是MVCC,undo log中的行就是MVCC中的多版本,这个可能与我们所理解的MVCC有较大的出入,一般我们认为MVCC 有下面几个特点:∙每行数据都存在一个版本,每次数据更新时都更新该版本∙修改时Copy出当前版本随意修改,个事务之间无干扰∙保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)就是每行都有版本号,保存时根据版本号决定是否成功,听起来含有乐观锁的味道。
,而Innodb的实现方式是:∙事务以排他锁的形式修改原始数据∙把修改前的数据存放于undo log,通过回滚指针与主数据关联∙修改成功(commit)啥都不做,失败则恢复undo log中的数据(rollback)二者最本质的区别是,当修改数据时是否要排他锁定,如果锁定了还算不算是MVCC?Innodb的实现真算不上MVCC,因为并没有实现核心的多版本共存,undo log中的内容只是串行化的结果,记录了多个事务的过程,不属于多版本共存。
但理想的MVCC是难以实现的,当事务仅修改一行记录使用理想的MVCC模式是没有问题的,可以通过比较版本号进行回滚;但当事务影响到多行数据时,理想的MVCC据无能为力了。
比如,如果Transaciton1执行理想的MVCC,修改Row1成功,而修改Row2失败,此时需要回滚Row1,但因为Row1没有被锁定,其数据可能又被Transaction2所修改,如果此时回滚Row1的内容,则会破坏Transaction2的修改结果,导致Transaction2违反ACID。
理想MVCC难以实现的根本原因在于企图通过乐观锁代替二段提交。
修改两行数据,但为了保证其一致性,与修改两个分布式系统中的数据并无区别,而二提交是目前这种场景保证一致性的唯一手段。
二段提交的本质是锁定,乐观锁的本质是消除锁定,二者矛盾,故理想的MVCC难以真正在实际中被应用,Innodb只是借了MVCC这个名字,提供了读的非阻塞而已。
5.总结也不是说MVCC就无处可用,对一些一致性要求不高的场景和对单一数据的操作的场景还是可以发挥作用的,比如多个事务同时更改用户在线数,如果某个事务更新失败则重新计算后重试,直至成功。
这样使用MVCC会极大地提高并发数,并消除线程锁。
6. 参考资料∙Mysql官网∙/link.php?url=%2Fwiki%2FMySQL_Inter nals∙Understanding MySQL InternalsMVCC and Snapshot IsolationMVCC: Multi-version concurrency control(多版本并发控制)。
事务处理系统中,为了使得多个事务能够并发执行并得到正确结果,需要采用一定的并发控制协议。
一类最常见的并发控制协议就是Lock-Based Protocol,其中我最熟悉的就是立即更新悲观上锁,其实现方式如下:1、当需要读/写一个item的时候,获取对应的锁,一直持有到commit或abort。
2、所有的更新操作是立即修改对应数据,修改发生之前会试图把这个item的前像(pre-image)存下来,如果已存在则不用了。
3、如果发生rollback,利用前像恢复到事务开始之前的状态。
4、如果成功commit,那么丢弃所有前像。
MVCC 则是另一类并发控制协议。
其基本思想是:每个事务在提交时,这个时刻该数据库的所有已提交数据构成一个快照,每个快照对应一个版本号。
每个事务工作在一个特定的版本上,也就是这个事务开始时数据库的版本,提交时再把它所修改的数据与数据库当前版本进行合并,不成功则retry。
前面所说的“并发执行并得到正确结果”是个很模糊的说法,准确来说,并发控制的目的是为了达到特定的隔离度。
SQL-92标准定义了4种隔离度:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE。
最初,大多数数据库都是在这4种隔离度的定义下设计并实现的,但是现在又多了一种,Snapshot Isolation。
最早是Oracle先整出来的,MS SQL Server从2005版开始加入这个。
MySQL InnoDB没有明确的把snapshot作为一个隔离度提出来,它声称提供了SQL92标准的全部4种隔离度,但是其实拿着snapshot、mvcc 在里面混水摸鱼,搞的四不像。
InnoDB的repeatable read isolation其实要比SQL92标准中规定的强,例如一个transaction反复执行select * from tableA;另一个往tableA里面插入数据。