READ_COMMITTED_SNAPSHOT的演示:
下面演示一个使用AdventureWorks 数据库的READ_COMMITTED_SNAPSHOT的例子,方便大家理解READ_COMMITTED_SNAPSHOT
在此示例中,使用行版本控制的已提交读事务与其他事务并发运行。已提交读事务的行为与快照事务的行为有所不同。与快照事务相同的是,即使其他事务修改了数据,已提交读事务也将读取版本化的行。然而,与快照事务不同的是,已提交读将执行下列操作:
在其他事务提交数据更改后,读取修改的数据。
能够更新由其他事务修改的数据,而快照事务不能。 在会话 1 上: USE AdventureWorks; GO
-- 在数据库上开启READ_COMMITTED_SNAPSHOT。
ALTER DATABASE AdventureWorks SET READ_COMMITTED_SNAPSHOT ON; GO
-- 开始一个read-committed级别的事务
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; GO
BEGIN TRANSACTION;
--选择EmployeeID号为4的员工的休假资料 SELECT EmployeeID, VacationHours FROM HumanResources.Employee WHERE EmployeeID = 4;
在会话 2 上:
USE AdventureWorks;
GO -- 开始一个事务 BEGIN TRANSACTION; --我们修改了EmployeeID为4的员工的休假资料 UPDATE HumanResources.Employee SET VacationHours = VacationHours - 8 WHERE EmployeeID = 4;
-- 确认下现在EmployeeID为4的员工的休假资料
SELECT VacationHours FROM HumanResources.Employee WHERE EmployeeID = 4;
在会话 1 上:
--因为会话2的事务没有提交, --EmployeeID为4的员工的休假资料因该没变 SELECT EmployeeID, VacationHours FROM HumanResources.Employee WHERE EmployeeID = 4;
在会话 2 上:
--提交我们的更新 COMMIT TRANSACTION; GO
在会话 1 上:
--OK,现在看看小4同志的资料
SELECT EmployeeID, VacationHours FROM HumanResources.Employee WHERE EmployeeID = 4;
--现在我们也来尝试下修改小4同志的资料
--ROLLBACK之后小4的数据到底是什么?你知道吗?UPDATE HumanResources.Employee SET SickLeaveHours = SickLeaveHours - 8 WHERE EmployeeID = 4; ROLLBACK TRANSACTION; GO 回顾一下SNAPSHOT的构架: SNAPSHOT隔离就像真实的快照,它会无视涉及行的变化。在SNAPSHOT隔离下运行的事务将读取数据,然后由另一事务修改此数据。 SNAPSHOT事务不阻塞由其他事务执行的更新操作,它忽略数据的修改继续从版本化的行读取数据。但是,当快照事务尝试修改已由其他事务修改的数据 时,SNAPSHOT事务将生成错误并终止. 相比READ_COMMITTED_SNAPSHOT,SNAPSHOT真正做到了快照隔离,完全无视数据的更新。相对 READ_COMMITTED_SNAPSHOT,它更进一步减轻了对锁的依赖,在性能方面获得了更大的优势。不可避免的是,SNAPSHOT的事务性也 变得更差,但是,至少,它比NoLock要好。^_^ SNAPSHOT的限制:
执行 ALTER INDEX 语句后,任何在执行 ALTER INDEX 语句时处于活动状态的快照事务,如果试图引用 HumanResources.Employee 表,都将收到错误。而使用行版本控制的已提交读事务不受影响。 3.BULK INSERT 操作可能会导致对目标表元数据的更改(例如,禁用约束检查时)。如果出现这种情况,访问大容量插入表的并发快照隔离事务将失败。 设置SNAPSHOT: 设置SNAPSHOT隔离模式也很简单,只要我们简单的一步操作就可以实现。 ALTER DATABASE DATABASE_NAME SET ALLOW_SNAPSHOT_ISOLATION ON; 但是要注意:如果 ALLOW_SNAPSHOT_ISOLATION 数据库选项设置为 ON,则数据库中数据已修改的所有活动事务完成之前,Microsoft SQL Server Database Engine 实例不会为已修改的数据生成行版本。如果存在活动的修改事务,SQL Server 将把该选项的状态设置为 PENDING_ON。所有修改事务完成后,该选项的状态更改为 ON。在该选项完全处于 ON 状态之前,用户无法在数据库中启动快照事务。数据库管理员将 ALLOW_SNAPSHOT_ISOLATION 选项设置为 OFF 后,数据库将跳过 PENDING_OFF 状态。 下面是ALLOW_SNAPSHOT_ISOLATION 选项的各个状态
SNAPSHOT的使用: 下面是使用READ_COMMITTED_SNAPSHOT的一个例子:
下面的代码示例显示了已修改为从事务隔离级别更改为已提交读隔离级别的相同 SELECT 语句。由于此更改,SELECT 语句将成功执行。
SNAPSHOT的演示: 在此示例中,在快照隔离下运行的事务将读取数据,然后由另一事务修改此数据。快照事务不阻塞由其他事务执行的更新操作,它忽略数据的修改继续从版本化的行读取数据。但是,当快照事务尝试修改已由其他事务修改的数据时,快照事务将生成错误并终止。
在会话 1 上: --在数据库上开启snapshot隔离级别. |