Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 读取提交的快照与快照隔离级别_Sql Server_Snapshot_Isolation Level_Read Committed Snapshot - Fatal编程技术网

Sql server 读取提交的快照与快照隔离级别

Sql server 读取提交的快照与快照隔离级别,sql-server,snapshot,isolation-level,read-committed-snapshot,Sql Server,Snapshot,Isolation Level,Read Committed Snapshot,有人能帮我理解什么时候在SQL Server中使用快照隔离级别胜过读取提交的快照吗 我知道在大多数情况下,读取提交的快照是有效的,但不确定何时进行快照隔离 感谢读取提交的快照执行乐观读取和悲观写入。相反,SNAPSHOT执行乐观读取和乐观写入 对于大多数需要行版本控制的应用程序,Microsoft建议读取提交的快照 阅读这篇优秀的Microsoft文章:。它解释了两种隔离级别的好处和成本 这里有一个更彻底的例子: [![隔离等级表][2][2] 请参见下面的示例: 读取提交的快照 更改数据库属性

有人能帮我理解什么时候在SQL Server中使用快照隔离级别胜过读取提交的快照吗

我知道在大多数情况下,读取提交的快照是有效的,但不确定何时进行快照隔离


感谢

读取提交的快照
执行乐观读取和悲观写入。相反,
SNAPSHOT
执行乐观读取和乐观写入

对于大多数需要行版本控制的应用程序,Microsoft建议读取提交的快照

阅读这篇优秀的Microsoft文章:。它解释了两种隔离级别的好处和成本

这里有一个更彻底的例子:

[![隔离等级表][2][2]

请参见下面的示例:

读取提交的快照

更改数据库属性,如下所示

ALTER DATABASE SQLAuthority
SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
GO
第1课时

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1
COMMIT
USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2
COMMIT
第二课时

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1
USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2
SELECT *
FROM   DemoTable
WHERE i = 2
COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2
结果–会话2中的查询显示旧值(1,1),因为当前事务未提交。这也是避免阻塞和读取提交数据的方法

第1课时

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1
COMMIT
USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2
COMMIT
第二课时

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1
USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2
SELECT *
FROM   DemoTable
WHERE i = 2
COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2
结果–会话2中的查询不显示行,因为在会话1中更新了行。因此,我们再次看到提交的数据

快照隔离级别

这是新的隔离级别,从SQLServer2005开始提供。对于此功能,应用程序中需要进行更改,因为它必须使用新的隔离级别

使用以下命令更改数据库设置。我们需要确保数据库中没有事务

ALTER DATABASE SQLAuthority SET AllOW_SNAPSHOT_ISOLATION ON
现在,我们还需要使用下面的命令来更改连接的隔离级别

第1课时

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1
COMMIT
USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2
COMMIT
第二课时

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1
USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2
SELECT *
FROM   DemoTable
WHERE i = 2
COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2
结果-即使我们将值更改为10,我们仍将在会话2中看到旧记录(2,2)

现在,让我们在会话1中提交事务

第1课时

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1
COMMIT
USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2
COMMIT
让我们回到会话2,再次运行select

第二课时

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1
USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2
SELECT *
FROM   DemoTable
WHERE i = 2
COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2
我们仍将看到该记录,因为会话2已使用快照隔离声明了事务。除非我们完成交易,否则我们将看不到最新记录

第二课时

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1
USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2
SELECT *
FROM   DemoTable
WHERE i = 2
COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2
现在,我们不应该看到该行,因为它已经更新


参见:,

仍然相关,从比尔的评论开始,我读了更多,并做了一些可能对其他人有用的笔记

默认情况下,单个语句(包括SELECT)处理“提交的”数据(READ COMMITED),问题是:它们是否等待数据“空闲”,并在读取时停止其他语句的工作

通过右键单击DB“属性->选项->杂项”进行设置:

并发/阻塞:读提交快照是否处于打开状态[默认为关闭,应处于打开状态]:

  • 使用快照进行选择(读取),不要等待其他快照,也不要阻止其他快照
  • 在不更改代码的情况下影响操作
  • ALTER DATABASE SET READ_COMMITTED_SNAPSHOT[打开|关闭]
  • 选择名称,是否从sys.databases读取\u提交\u快照\u打开
一致性:允许快照隔离[默认关闭,可讨论-确定关闭]:

  • 允许客户端跨SQL语句(事务)请求快照
  • 代码必须请求“事务”快照(如设置事务…
  • ALTER DATABASE SET ALLOW_SNAPSHOT_ISOLATION[打开|关闭]
  • 从系统数据库中选择名称、快照\u隔离\u状态
问题:读取提交的快照和允许快照隔离之间不是一个或另一个。它们是快照的两种情况,可以单独打开或关闭,而允许快照隔离则是一个更高级的主题。允许快照隔离允许代码进一步控制快照区域

如果只考虑一行,问题似乎很清楚:默认情况下,系统没有副本,因此如果有人在写,读卡器必须等待,如果有人在读,写卡器也必须等待——行必须一直锁定。启用“正在读取已提交的快照”将激活数据库以支持“快照副本”,以避免这些锁定

漫无目的地说……

在我看来,对于任何正常的MS SQLServer数据库,“Is Read Committed Snapshot On”都应该是真的,并且默认情况下,它是一个过早的优化,它附带了FALSE


但是,有人告诉我,一行锁变得更糟糕,不仅因为您可能要跨表寻址多行,还因为在SQL Server中,行锁是使用“块”级锁(锁定与存储邻近性相关联的随机行)实现的,并且存在一个阈值,多个锁触发表锁定——可能更多“乐观”的性能优化可能会在繁忙的数据库中出现阻塞问题。

如果不讨论快照中可能发生的可怕的“快照更新冲突”异常(但不是快照读取已提交),则快照和快照读取已提交的比较是不完整的

简言之,快照隔离在事务开始时检索已提交数据的快照,然后对读取和写入使用乐观锁定。如果在尝试提交事务时,发现其他内容更改了某些相同数据,则数据库将回滚整个事务并引发错误ca在调用代码中使用快照更新冲突异常。这是因为受事务影响的数据在事务结束时的版本与开始时的版本不同

Snapshot Read Committed不会遇到此问题,因为它在写入时使用锁定(悲观写入),并在每个语句的stat处获取所有已提交数据的快照版本信息

波西