我们在Oracle和MySQL数据库中已经对一致性读的概念比较熟悉了,但是在SQL Server中却鲜少提及,但SQL Server自2005版本以来其实也实现了一致性读,几乎所有关系型数据库产品的一致性读都是通过MVCC机制实现的,说白了就是修改之前先把数据存一份儿。
MVCC的意思就是Multi-Version Concurrency Control--多版本并发控制,这里的version就是指的数据的前镜像,多了一份数据自然就减少了争用,增加了并发。
SQL Server数据库在Read committed snapshot和snapshot隔离级别下通过MVCC机制实现了一致性读,其机制如下:
MVCC一致性读步骤:
- A new transaction is initiated, and it is assigned a transaction sequence number.
- 每个事务开始时被分配一个事务序列号Transaction Sequence Number(TSN)。
- The Database Engine reads a row within the transaction and retrieves the row version from tempdb whose sequence number is closest to, and lower than, the transaction sequence number.
- 读事务通过数据库引擎在tempdb中检索TSN小于当前读事务TSN的行(这些行都带有各自事务的TSN信息)。
- The Database Engine checks to see if the transaction sequence number is not in the list of transaction sequence numbers of the uncommitted transactions active when the snapshot transaction started.
- 数据库引擎检查:步骤2中找到的行的TSN是否在未提交事务列表中,此列表中的未提交事务都是读事务启动时就已经处于active状态的事务。
- The transaction reads the version of the row from tempdb that was current as of the start of the transaction. It will not see new rows inserted after the transaction was started because those sequence number values will be higher than the value of the transaction sequence number.
- 当前事务只读取:离当前读事务TSN最近,且小于当前读事务TSN的行版本。这意味只读取最新的已提交数据。
- The current transaction will see rows that were deleted after the transaction began, because there will be a row version in tempdb with a lower sequence number value.
- 当前事务永远不会读取到其他事物的未提交修改,因为在tempdb中总会存在修改行的行版本(即前镜像)。
在读事务开始后有其他DML事务修改、插入、删除数据并在读到数据之前就提交,那么读事务会不会读取到这些更新?
由于条件所限,还未进行测试,但是猜测如下:
不会读取到更新,因为这些行版本会在tempdb中保留一段时间(同一数据可能存在多个行版本),只要检测到这些行版本的TSN大于当前读事务的TSN那么就意味着这些行在读事务开启后经过了修改,读事务只要找到这些行版本中TSN最新的一个就可以。
如果猜测正确那么也意味着tempdb中的行版本(即行的前镜像)是有保留时间的,类似于Oracle的Undo_retention。
如果猜测与实践不符,那么就意味着tempdb中的行版本会在事务提交后立马消失,读事务会读取到事务开始后的一部分提交的修改。
本文主要观点来自官网博客:
关于Read committed snapshot和snapshot隔离级别,参考http://www.cnblogs.com/leohahah/p/8464575.html