四种隔离级别:
隔离级别 | 脏 读 | 不可重复读取 | 幻 像 |
---|---|---|---|
读操作未提交(Read Uncommitted) | 是 | 是 | 是 |
读操作已提交(Read Committed) | 否 | 是 | 是 |
可重复读(Repeatable Read) | 否 | 否 | 是 |
快照 | 否 | 否 | 否 |
可串行读(Serializable) | 否 | 否 | 否 |
SQL Server 还支持使用行版本控制的两个事务隔离级别:已提交读隔离 和 新事务隔离级别(快照)。
- READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON,提供语句级读取一致性。
- ALLOW_SNAPSHOT_ISOLATION 数据库选项设置为 ON,提供事务级别的读取一致性。读取操作不获取页锁或行锁,读取其他事务修改的行时,读取操作将检索启动事务时存在的行的版本。(快照隔离)
- SQL Server 不支持元数据的版本控制。在快照隔离下,显式事务中可以执行的 DDL 操作存在限制,BEGIN TRANSACTION 语句之后不允许使用任何公共语言运行时 (CLR) DDL 语句或下列 DDL 语句:ALTER TABLE、CREATE INDEX、CREATE XML INDEX、ALTER INDEX、DROP INDEX、DBCC REINDEX、ALTER PARTITION FUNCTION、ALTER PARTITION SCHEME。
- 已提交读隔离比快照隔离占用的 tempdb 空间少;已提交读隔离可用于分布式事务,而快照隔离不能用于分布式事务;已提交读隔离可用于大多数现有应用程序,而不需要进行任何更改。可以动态优化使用默认隔离级别(已提交读)编写的应用程序。已提交读的行为(是否使用行版本控制)是由数据库选项设置确定的,可以对其进行更改,而不会影响应用程序。
- 快照隔离很容易发生不适用于使用行版本控制的已提交读隔离的更新冲突。当在快照隔离下运行的事务读取另一个事务稍后会修改的数据时,快照事务对同一数据的更新会导致更新冲突,该事务将终止并回滚。而使用行版本控制的已提交读隔离不存在此问题。
隔离级别是根据称为 现象(Phenomena)的三个禁止操作序列来声明的:
名称 | 描述 |
---|---|
丢失更新
| 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,就会发生这种情况。
|
脏读 | 如果一个事务在提交操作结果之前,另一个事务可以看到该结果,就会发生这种情况。
|
不可重复读/模糊读 | 如果一个事务在提交结果之前,另一个事务可以修改和删除它,就会发生这种情况。
|
幻像读 | 当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,就会发生这种情况。 有删除,有新增。 |
锁分类 | 关键字 |
---|---|
粒度 | ROWLOCK, PAGLOCK, TABLOCK, DBLOCK |
模式 | UPDLOCK, XLOCK |
并发 | NOLOCK, HOLDLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLEs |
|
Transaction中IsolationLevel的类型定义如下:
Chaos 无法改写隔离级别更高的事务中的挂起的更改。
ReadCommitted 在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。
ReadUncommitted 可以进行脏读,意思是说,不发布共享锁,也不接受独占锁。
RepeatableRead 在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。防止不可重复的读取,但是仍可以有幻像行。
使用该隔离级别将限制其他用户更新自己所持有的数据,以PK,IX(Unique)为依据的不限制插入。
Serializable 在DataSet上放置范围锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行。
使用该隔离级别将限制其他用户更新自己所持有的数据,限制其他用户插入数据。
Unspecified 正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。
附测试C#代码:
SQL Query:
-- BEGIN TRANSACTION
INSERT INTO Task (TaskID,SenderAliasID,TaskStatus)
VALUES('2009081215121000',3,3)
-- waitfor delay '00:00:00.200'
DELETE FROM Task WHERE TaskID='2009081215121000'
-- COMMIT
.