赞
踩
MVCC(Multi-Version Concurrency Control)是一种多版本并发控制机制,主要用于数据库管理系统中,实现对数据库的并发访问。在编程语言中,MVCC可以实现事务内存。
MVCC的特点是读不加锁,读写不冲突。MVCC将读操作分为快照读和当前读。快照读读取的是记录的可见版本,不需要加锁。当前读读取的是记录的最新版本,并对当前读返回的记录加锁,以保证其他事务不会并发修改该记录。快照读一般用于简单的SELECT操作,当前读一般用于SELECT * FROM table WHERE lock in share mode(允许不同事务之间共享加锁读取S锁,不允许其他事务修改或者加排他锁)、SELECT * FROM table WHERE for update(排他锁X锁)、INSERT INTO table VALUES(插入操作)、UPDATE table SET WHERE(更新操作)、DELETE FROM table WHERE(删除操作)等特殊读操作。
为什么需要MVCC呢?数据库通常使用锁来实现隔离性。最原生的锁,锁住一个资源后会禁止其他任何线程访问同一个资源。但是很多应用的一个特点都是读多写少的场景,很多数据的读取次数远大于修改的次数,而读取数据间互相排斥显得不是很必要。所以就使用了一种读写锁的方法,读锁和读锁之间不互斥,而写锁和写锁、读锁都互斥。这样就很大提升了系统的并发能力。之后人们发现并发读还是不够,又提出了能不能让读写之间也不冲突的方法,就是读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了,不同的事务session会看到自己特定版本的数据。当然快照是一种概念模型,不同的数据库可能用不同的方式来实现这种功能。
InnoDB的MVCC,是通过在每行纪录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建版本号,一个保存了行的删除版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行纪录的版本号进行比较。在REPEATABLE READ隔离级别下,MVCC具体的操作如下:
undo log 在不考虑redo log 的情况下利用undo log工作的简化过程为:
1)为了保证数据的持久性数据要在事务提交之前持久化
2)undo log的持久化必须在在数据持久化之前,这样才能保证系统崩溃时,可以用undo log来回滚事务
Innodb中的隐藏列
Innodb通过undo log保存了已更改行的旧版本的信息的快照。 InnoDB的内部实现中为每一行数据增加了三个隐藏列用于实现MVCC。
SELECT
InnoDB会根据以下两个条件检查每行纪录:
InnoDB只查找版本早于当前事务版本的数据行,即,行的系统版本号小于或等于事务的系统版本号,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
行的删除版本,要么未定义,要么大于当前事务版本号。这样可以确保事务读取到的行,在事务开始之前未被删除。
只有符合上述两个条件的纪录,才能作为查询结果返回。
INSERT
InnoDB为插入的每一行保存当前系统版本号作为行版本号。
DELETE
InnoDB为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE
InnoDB为插入一行新纪录,保存当前系统版本号作为行版本号,同时,保存当前系统版本号到原来的行作为行删除标识。
MVCC在大多数情况下代替了行锁,实现了对读的非阻塞,读不加锁,读写不冲突。缺点是每行记录都需要额外的存储空间,需要做更多的行维护和检查工作。
补充:
1.MVCC手段只适用于Msyql隔离级别中的读已提交(Read committed)和可重复读(Repeatable Read)。
2.Read uncimmitted由于存在脏读,即能读到未提交事务的数据行,所以不适用MVCC.
原因是MVCC的创建版本和删除版本只要在事务提交后才会产生。
3.串行化由于是会对所涉及到的表加锁,并非行锁,自然也就不存在行的版本控制问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。