写时复制和多版本并发控制,都能够实现读事务不加锁。下面介绍mvcc,以mysql innodb存储引擎为例子。
innodb每一行维护了两个隐含的列,一个存储了行被修改的时间,一个是行被删除的时间。这个时间 不是绝对时间,而是与数据库系统对应的版本号,每当一个事物开始时,innodb会给这个事物一个递增的版本号,所以版本号也可以认为是事物号。对于每一行查询语句,innodb都会把这个查询语句的版本号同这个查询语句遇到的行的版本号进行对比,然后结合不同的事物隔离级别,来决定是否返回改行。
1.select
对于select语句,只有同时满足了下面两个条件的行,才会被返回。
a)行的修改版本号小于等于该事物号。
b)行的删除版本号要么没有定义,要么大于事物的版本号。
如果行的修改或者删除版本号大于事物号,说明行是被该事物后面启动的事物修改或者删除的。在可重复读取隔离的级别下,后开始事物对数据的影响不应该被先前的事物看见,所以应该忽略后开始的事物的更新或则删除操作。
insert
新插入的行,行的修改版本号更新为该事物版本号
delete
innodb把改行的删除的版本号设置为该事物的版本号,标记为删除,而不是物理删除。
update
在更新行的时候,innodb会把原来的行复制一份,该行的修改版本号即为事物版本号
mvcc读书数据不用加锁,查询通过版本检查,获取需要的版本,大大提高了系统的并发度。当然,为了实现多版本,必须对每行存储多个版本的数据。
mvcc会定期检查版本,删除不需要的版本数据。