什么是快照隔离?
DBMS 中的隔离级别用于维护事务的并发执行,而不会因脏读、幻读和不可重复读等问题而中断。快照隔离就是一种实现最大并发级别的隔离级别。
在本文中,我们将了解两个概念:
- 快照隔离
- 行版本控制技术
快照隔离级别:
在基于锁的隔离级别中,读取数据的事务会阻塞试图写入数据的事务,反之亦然,从而降低并发级别并降低系统性能。为了克服这个问题,引入了快照隔离。快照隔离不是在事务上获取键范围锁,而是使用行版本控制。
行版本控制技术:
在 SQL Server 中,行版本可以定义为一种数据类型,它有助于对具有唯一值的表的行进行版本标记。在行版本控制中,SQL 服务器将由事务修改的行的所有旧副本存储在tempDB中。如果一个特定的行被多次修改,那么该行的多个旧副本将存储在 tempdb 中,只要它们是任何正在进行或即将发生的事务所需的时间。
“快照”这个名称着重于这样一个事实,即所有事务查询都可以使用类似的数据库副本,就像在事务开始时一样。快照隔离中的行版本控制技术帮助 SQL 服务器避免锁定,从而允许读取数据的事务不阻塞修改数据的事务,反之亦然。但是一个事务写入数据可能会阻塞其他试图同时写入数据的事务,这是快照隔离中发生的更新冲突。由于此更新冲突,两个事务中的任何一个都需要回滚或者需要被终止。
快照隔离的属性:
- 无冲突:快照隔离遵循乐观并发控制,即事务之间不太可能发生冲突。
- 前缀:每个节点可以按相似的顺序查看交易。
- 内部一致性:事务中的读操作,只会观察属于该事务的最新写操作。
- 外部一致性:在两个事务 T1 和 T2 中,T2 之前没有写操作的读操作将观察事务 T1 写入的状态,条件是没有其他事务写入 T1。
例如:考虑这样一种情况,一批六名学生根据他们的卷号是偶数还是奇数分成两组,每组三人。以前,Team-1 包含的学生的卷号为偶数,而 Team-2 的学生的卷号为奇数。一段时间后,老师决定改为 Team-1 有奇数学生,Team-2 有偶数学生。为此,使用了两个并发事务,T1 将奇数变为偶数,T2 将偶数变为奇数。
正如我们所看到的,最后的表格将包含所有具有奇数卷号的成员或每个具有偶数卷号的成员。这是因为在可序列化执行中,一次只会运行一个事务。 T1 将仅以偶数滚动号码离开桌子,在 T1 之后,T2 会将所有偶数滚动号码转换为奇数。
使用快照隔离检查这些事务的结果,我们可以注意到 T1 和 T2 都在使用存储在 tempDB 中的先前版本的数据库。 T1 选择所有奇数滚动编号并将它们转换为偶数,同时 T2 选择具有偶数滚动编号的行(不包括被 T1 更改为偶数的行)并将它们修改为奇数。这样,我们就可以精确地切换每个候选卷号的类型
各种快照隔离级别:
- Read-Committed Snapshot Isolation (RCSI):在 RCSI 中,SQL 服务器在语句级别维护由写入操作进行的数据更新的快照,即快照的生命周期较短。数据读取器将在读取语句开始之前从 tempDB 获取存储在最后提交的快照或版本中的数据。 RCSI 也称为语句级快照隔离级别。
- 快照隔离:在快照隔离中,SQL 服务器在事务级别维护由写操作进行的数据更新的快照,即在事务的生命周期内维护快照。数据读取器将在事务开始之前从 tempDB 获取存储在最后提交版本中的数据。快照隔离也称为事务级快照隔离级别。
快照隔离的限制:
除了开启快照隔离给系统带来的所有优势外,快照级别也有一定的限制。
- 为更新 tempDB 中的数据的每个事务维护行版本的额外开销。
- 读写操作不会互相阻塞,但两个写操作之间仍然会发生阻塞(称为更新冲突)。