读取已提交的快照VS快照隔离级别
有人可以帮我理解什么时候使用SQL Server中的READ COMMITTED SNAPSHOT SNAPSHOT隔离级别?
我明白在大多数情况下,READ COMMITTED SNAPSHOT工作,但不知道什么时候进行SNAPSHOT隔离。
谢谢
READ COMMITTED SNAPSHOT
乐观读取和悲观写入。 相比之下, SNAPSHOT
乐观的读取和乐观的写道。
对于大多数需要行版本控制的应用程序,Microsoftbuild议使用READ COMMITTED SNAPSHOT
。
阅读这篇出色的Microsoft文章: select基于行版本控制的隔离级别 。 它解释了两个隔离级别的好处和成本。
这里是一个更彻底的: http : //msdn.microsoft.com/en-us/library/ms345124(SQL.90).aspx
看下面的例子:
读取提交的快照
如下所示更改数据库属性
ALTER DATABASE SQLAuthority SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE GO
第一部分
USE SQLAuthority GO BEGIN TRAN UPDATE DemoTable SET i = 4 WHERE i = 1
第二部分
USE SQLAuthority GO BEGIN TRAN SELECT * FROM DemoTable WHERE i = 1
结果 – 由于当前事务未提交,因此会话2中的查询显示旧值(1,ONE)。 这也是避免阻塞和读取已提交数据的方法。
第一部分
COMMIT
第二部分
USE SQLAuthority GO SELECT * FROM DemoTable WHERE i = 1
结果 – 会话2中的查询显示没有行,因为行在会话1中更新。所以我们再次看到提交的数据。
快照隔离级别
这是从SQL Server 2005开始提供的新的隔离级别。 对于此function,应用程序需要进行更改,因为它必须使用新的隔离级别。
使用下面的数据库设置更改 我们需要确保数据库中没有事务。
ALTER DATABASE SQLAuthority SET AllOW_SNAPSHOT_ISOLATION ON
现在,我们还需要使用下面的方法来改变连接的隔离级别
第一部分
USE SQLAuthority GO BEGIN TRAN UPDATE DemoTable SET i = 10 WHERE i = 2
第二部分
SET TRANSACTION ISOLATION LEVEL SNAPSHOT GO USE SQLAuthority GO BEGIN TRAN SELECT * FROM DemoTable WHERE i = 2
结果 – 即使我们已经将值更改为10,我们仍然会在会话2(2,TWO)中看到旧logging。
现在,我们在会话1中提交事务
第一部分
COMMIT
让我们回到会话2并再次运行select。
第二部分
SELECT * FROM DemoTable WHERE i = 2
我们仍然会看到logging,因为会话2已经说明了与快照隔离的事务。 除非我们完成交易,否则我们不会看到最新的logging。
第二部分
COMMIT SELECT * FROM DemoTable WHERE i = 2
现在,我们不应该看到行已经更新。
请参阅: SQL权威 , Safari联机丛书
仍然相关,从比尔的评论开始,我读了更多,并提出可能对其他人有用的笔记。
默认情况下,单个语句(包括“SELECT”)在“提交”数据(READ COMMITTED)上工作,问题是:他们是否等待数据“空闲”并在读取时阻止其他人工作?
通过右键单击DB“Properties – > Options – > Miscellaneous”来设置:
并发/阻塞:读取提交快照开启 [默认closures,应该打开]:
- 使用SNAPSHOTselect(读取),不要等待其他人,也不要阻止他们。
- 效果操作无需更改代码
- ALTER DATABASE SET READ_COMMITTED_SNAPSHOT [ON | OFF]
- SELECT名称,is_read_committed_snapshot_on FROM sys.databases
一致性:允许快照隔离 [默认closures,可辩论 – closures]:
- 允许客户端跨SQL语句(事务)请求SNAPSHOT。
- 代码必须请求“事务”快照(如SET TRANSACTION …)
- ALTER DATABASE SET ALLOW_SNAPSHOT_ISOLATION [ON | OFF]
- SELECT名称,is_read_committed_snapshot_on FROM sys.databases
对于这个问题:读取提交的快照和允许快照隔离之间不是一个或另一个。 它们是两种快照,可以单独打开或closures,允许快照隔离是一个高级主题。 允许快照隔离允许代码进一步控制快照区域。
这个问题似乎很清楚,如果你考虑一行:在默认情况下,系统没有副本,所以读者必须等待,如果有其他人正在写,并且作家还必须等待,如果其他人正在阅读 – 该行必须locking所有时间。 启用“提交读取提交快照”激活数据库以支持“快照副本”以避免这些locking。
在…上…
在我看来,“Read Committed Snapshot On”对于任何普通的MS SQLServer数据库都应该是“TRUE”,并且默认情况下它是“FALSE”的过早优化。
但是,我被告知一行锁越来越差,不仅因为你可能在表中寻址多行,而且因为在SQL Server中,行锁使用“块”级锁(locking与存储邻近关联的随机行)来实现,有一个阈值,其中多个锁触发表锁 – 大概是更乐观的性能优化,在忙数据库中阻塞问题的风险。