标签:时间 mit 执行 session option 共享锁 options single 一致性
隔离级别定义事务操作资源和更新数据的隔离程度,在SQL Server中,隔离级别只会影响读操作申请的共享锁,而不会影响写操作申请的互斥锁。隔离级别控制事务在执行读操作时:
在执行写操作时,事务持有互斥锁,直到事务结束才释放,互斥锁不受事务隔离级别的影响。隔离性和并发性是此消彼长的关系。在SQL Server中,互斥锁和任意锁都不兼容,在同一时间,同一个数据行上,只能有一个事务持有互斥锁,就是说,写操作是顺序进行的,不能并发。
Choosing a transaction isolation level does not affect the locks acquired to protect data modifications. A transaction always gets an exclusive lock on any data it modifies, and holds that lock until the transaction completes, regardless of the isolation level set for that transaction.
事务的隔离级别共有5个,使用SET命令修改Session-Level的隔离级别,使用DBCC UserOptions 查看当前Session的隔离级别:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE DBCC UserOptions
一,事务的隔离级别
SQL Server 默认的隔离级别是Read Committed,用户不能修改Database-Level默认的隔离级别,但能够修改Session-Level默认的隔离级别。Session-Level默认的隔离级别是Read Committed,该隔离级别受到数据库选项 READ_COMMITTED_SNAPSHOT 的影响,决定Read Committed隔离级别是否使用行版本控制事务的读操作,在Read Committed隔离级别下:
在任何隔离级别下,事务在执行写操作时都申请互斥锁(exclusive lock),持有互斥锁直到事务结束,互斥锁不受隔离级别的控制;而共享锁(Shared Lock)受到隔离级别的控制,隔离级别影响Shared Lock的申请和释放:
SQL Server支持使用Row Versioning的隔离级别,事务的读操作只申请SCH-S 表级锁,不会申请Page 锁和Row 锁:
二,使用Row Versioning的隔离级别
在默认的隔离级别Read Commited下,在执行读操作时,事务申请shared lock,读写操作相互阻塞。在隔离级别Read Uncommitted下,事务不会申请shared lock,因此读操作不会阻塞写操作,但是读操作可能会读到脏数据。脏数据是指被其它尚未提交的事务修改之后的数据值,不是指更新之前的数据值。
SQL Server 提供Snapshot隔离级别,用于读取修改之前的数据值。在Snapshot隔离级别下,事务在修改任何数据之前,先将修改前的数据复制到tempdb,写操作创建数据行的一个原始版本(Row Version),注意,SQL Server只会复制被修改的数据行,对于未修改的数据行,不会保存行版本数据。后续其他事务的一切读操作都去读这个复制的行版本。在Snapshot隔离级别下,读写操作不会互相阻塞。使用行版本控制提高事务的并发性,但是有一个明显的缺点,虽然用户读到的不是脏数据,但是数据可能正在被修改,很快就要过期。如果根据这个过期的数据做数据修改,可能会产生逻辑错误。
1,启用Snapshot隔离级别
设置数据库选项 ALLOW_SNAPSHOT_ISOLATION 为 ON,没有改变Session-Level的事务隔离级别,需要修改Session-Level的事务隔离级别为SNAPSHOT,才能使用行版本数据
alter database current set allow_snapshot_isolation on;
要想使用snapshot隔离级别,必须将当前Session的隔离级别修改Snapshot,这样当前的事务才能访问Row Versioning数据:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
2,数据库选项READ_COMMITTED_SNAPSHOT(简称RCS)
使用Row-Versioning数据时,数据库选项ALLOW_SNAPSHOT_ISOLATION必须设置为ON,将数据库选项READ_COMMITTED_SNAPSHOT设置为ON,在默认的隔离级别Read Committed下,事务能够访问Row Versioning数据:
alter database current set allow_snapshot_isolation on; alter database current set read_committed_snapshot on;
前提是必须设置数据库选项ALLOW_SNAPSHOT_ISOLATION为ON,一旦启用RCS选项,在默认的Read Committed 隔离级别中,事务使用行版本(row versioning)代替加锁,事务能够访问版本化的数据行。Read Committed Snapshot隔离级别保证语句级别的事务一致性,TSQL语句只能读取在该语句开始时已经提交的数据。当前事务的读操作不会阻塞其他事务的写操作,当前事务读取的是其他事务已提交修改的数据值。
When a transaction runs at the read committed isolation level, all statements see a snapshot of data as it exists at the start of the statement. Setting the READ_COMMITTED_SNAPSHOT ON option allows access to versioned rows under the default READ COMMITTED isolation level.
3,READ COMMITTED Snapshot隔离级别
在Read Committed 隔离级别下,事务不能读取被其他事务修改,但尚未提交的数据,即只能读取已提交更新的数据,READ COMMITTED隔离级别的行为受到数据库选项:READ_COMMITTED_SNAPSHOT的影响:
4,快照隔离级别
SNAPSHOT 隔离级别指定在一个事务中读取的数据是一致性的数据版本。在事务开始时,在表级别创建数据快照,只能识别其他事务已提交的数据更新。在事务开始之后,当前事务不会识别其他事务执行的数据更新。Sanpshot隔离级别实现事务级别的数据一致性。SQL Server 使用tempdb来存储行版本化(row versioning)的数据,如果数据更新较多,存储的行版本太多,会导致tempdb成为系统瓶颈。
Specifies that data read by any statement in a transaction will be the transactionally consistent version of the data that existed at the start of the transaction. The transaction can only recognize data modifications that were committed before the start of the transaction. Data modifications made by other transactions after the start of the current transaction are not visible to statements executing in the current transaction. The effect is as if the statements in a transaction get a snapshot of the committed data as it existed at the start of the transaction.
三,启用快照隔离级别
1,使用snapshot 隔离级别
step1,设置数据库选项
ALTER DATABASE CURRENT SET SINGLE_USER
WITH ROLLBACK IMMEDIATE; ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON; --ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT OFF; ALTER DATABASE CURRENT SET MULTI_USER;
step2,修改Session-Level的隔离级别为snapshot
set transaction isolation level snapshot
2,使用Read_Committed_Snapshot隔离级别
ALTER DATABASE CURRENT SET SINGLE_USER WITH ROLLBACK IMMEDIATE; ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT ON; ALTER DATABASE CURRENT SET MULTI_USER;
四,引用徐海蔚老师的例子,测试隔离级别的行为
snapshot隔离级别不会阻塞其他事务的写操作,该隔离级别忽略数据的修改操作,只读取row versioning的数据,就是说,读取到的是数据修改之前的版本,当snapshot事务尝试修改由其他事务修改的数据时,产生更新冲突,写操作异常终止。
read committed snapshot隔离级别,读取行版本化的已提交数据:
参考文档:
Isolation Levels in the Database Engine
SQL SERVER – Difference Between Read Committed Snapshot and Snapshot Isolation Level
数据库的快照隔离级别(Snapshot Isolation)
标签:时间 mit 执行 session option 共享锁 options single 一致性
原文地址:http://www.cnblogs.com/ljhdo/p/5037033.html