请问有人可以帮助我了解何时在SQL Server中通过READ COMMITTED SNAPSHOT使用SNAPSHOT隔离级别吗?
我了解在大多数情况下,READ COMMITTED SNAPSHOT可以工作,但不确定何时进行SNAPSHOT隔离。
谢谢
Answers:
READ COMMITTED SNAPSHOT
乐观阅读和悲观写作。相反,SNAPSHOT
乐观读和乐观写。
Microsoft建议READ COMMITTED SNAPSHOT
大多数需要行版本控制的应用程序。
阅读这篇出色的Microsoft文章:选择基于行版本控制的隔离级别。它说明了两个隔离级别的好处和成本。
这里是更详尽的一个:http : //msdn.microsoft.com/zh-cn/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开始使用。对于此功能,由于必须使用新的隔离级别,因此应用程序需要进行更改。
使用下面的方法更改数据库设置。我们需要确保数据库中没有事务。
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,两个)。
现在,让我们在会话1中提交事务
第一场
COMMIT
让我们回到会话2并再次运行select。
第二场
SELECT *
FROM DemoTable
WHERE i = 2
我们仍将看到该记录,因为会话2已使用快照隔离声明了该事务。除非我们完成交易,否则不会看到最新记录。
第二场
COMMIT
SELECT *
FROM DemoTable
WHERE i = 2
现在,我们不应该看到该行,因为它已经更新。
如果不讨论可能在快照中发生的可怕的“快照更新冲突”异常,而不对“快照已提交”,则快照和“已提交快照读取”的比较是不完整的。
简而言之,快照隔离在事务开始时检索已提交数据的快照。,然后对读取和写入使用乐观锁定。如果在尝试提交事务时,发现其他更改更改了某些相同的数据,则数据库将回滚整个事务并引发错误,从而导致调用代码中出现快照更新冲突异常。这是因为受事务影响的数据版本在事务结束时与开始时不同。
快照已提交快照不受此问题的困扰,因为它使用了写锁定(悲观写),并且在每个语句的stat处获取所有已提交数据的快照版本信息。
快照更新和“未提交快照读取”中发生快照更新冲突的可能性是两者之间的极大差异。
仍然相关,从比尔的评论开始,我阅读了更多内容,并做了一些可能对其他人有用的笔记。
默认情况下,单个语句(包括SELECT)对“已提交”的数据(“读已提交”)起作用,问题是:它们是否在等待数据为“空闲”并阻止其他人在读取时工作?
通过右键单击DB“属性->选项->其他”进行设置:
并发/阻止:已提交读快照快照[默认关闭,应该打开]:
ALTER DATABASE <dbName> SET READ_COMMITTED_SNAPSHOT [ON|OFF]
SELECT name, is_read_committed_snapshot_on FROM sys.databases
一致性:允许快照隔离[默认关闭,有争议-确定关闭]:
SET TRANSACTION ...
)ALTER DATABASE <dbName> SET ALLOW_SNAPSHOT_ISOLATION [ON|OFF]
SELECT name, snapshot_isolation_state FROM sys.databases
的问题:它不是一个或读取提交快照和允许快照隔离的其他。它们是快照的两种情况,并且可以单独打开或关闭,“允许快照隔离”则是高级主题。允许快照隔离允许代码进一步控制快照范围。
如果您考虑一行,问题似乎很明显:默认情况下,系统没有副本,因此,如果有人在写,则读者必须等待,如果有人在阅读,则作家也必须等待–该行必须锁定所有时间。启用“正在读取提交的快照”将激活数据库以支持“快照副本”,以避免这些锁定。
bling ...
我认为,对于任何普通的MS SQLServer数据库,“正在读取已提交的快照”应该为TRUE,并且默认情况下它为FALSE是过早的优化。
但是,我被告知,单行锁会变得更糟,这不仅是因为您可能要处理跨表的多行,而且还因为在SQL Server中,行锁是使用“块”级锁实现的(锁定与存储相关性相关的随机行),并且存在多个锁触发表锁定的阈值-可能是更“乐观”的性能优化,可能会阻塞繁忙数据库中的问题。