Tra*_*vis 43 sql-server configuration isolation-level
大部分的论坛和榜样的网上总是建议同时拥有ALLOW_SNAPSHOT_ISOLATION并READ_COMMITTED_SNAPSHOT设置为ON,每当别人问快照,行版本或类似的问题。
我想这两种设置中的 SNAPSHOT 一词都有些令人困惑。我认为,为了让数据库引擎对 READ_COMMITTED 默认行为使用行版本控制而不是锁定,无论设置如何,数据库READ_COMMITTED_SNAPSHOT都设置为 ON 。ALLOW_SNAPSHOT_ISOLATION
该ALLOW_SNAPSHOT_ISOLATION设定被设定为ON只允许快照隔离启动事务(例如SET TRANSACTION ISOLATION级快照)时无论的READ_COMMITTED_SNAPSHOT设置。
将这两个设置设置为 ON 的唯一原因是它需要具有 READ COMMITTED 行版本控制和 快照隔离。
我的问题是,我的理解在某种程度上是错误的吗?并且这两个设置必须始终一起设置为 ON(特别是对于 READ COMMITTED 行版本控制)?
Ali*_*ghi 29
你的理解是正确的。它确实有点令人困惑。
Kim Tripp(SQL Server 的程序员之一,也是 SQLSkills 的一个组成部分)完全了解了您在有关快照隔离的MCM 视频中所说的内容。快进到视频中的 41:45 以进入她回答您问题的部分。
如果您使用请ALLOW_SNAPSHOT_ISOLATION确保您SET TRANSACTION ISOLATION LEVEL SNAPSHOT在您的代码中使用,否则您将无法获得任何好处。
如果设置了SET READ_COMMITTED_SNAPSHOT ON,则无需修改任何代码。MS SQL Server 自动为该表应用快照隔离。
我还没有测试过如果你在代码中要求不同的隔离级别会发生什么,我怀疑它会覆盖这个选项但首先测试它。
关于快照隔离如何改变应用程序预期行为的好文章。它显示了更新语句和选择语句如何返回完全不同和意外结果的示例。
Tra*_*vis 16
好的,回家测试。这是观察。
CREATE DATABASE TEST;
GO
CREATE TABLE TABLE1
(
ID tinyint,
Details varchar(10)
);
GO
INSERT INTO TABLE1
VALUES (1, 'Original');
GO
SELECT
name,
snapshot_isolation_state_desc,
is_read_committed_snapshot_on
FROM sys.databases
WHERE name = 'TEST';
GO
Run Code Online (Sandbox Code Playgroud)
第一次测试,确认两个设置都关闭。
查询 1
USE TEST;
BEGIN TRAN
UPDATE TABLE1
SET Details = 'Update'
WHERE ID = 1;
--COMMIT;
--ROLLBACK;
GO
Run Code Online (Sandbox Code Playgroud)
查询 2
USE TEST;
SELECT ID, Details
FROM TABLE1
WHERE ID = 1;
GO
Run Code Online (Sandbox Code Playgroud)
在此测试中,查询 2 正在等待查询 1 提交,dm_tran_locks DMV 显示查询 1 导致对 TABLE1 的排他锁。
USE TEST;
SELECT
DB_NAME(tl.resource_database_id) AS DBName,
resource_type,
OBJECT_NAME(resource_associated_entity_id) AS tbl_name,
request_mode,
request_status,
request_session_id
FROM sys.dm_tran_locks tl
WHERE
resource_database_id = db_id('TEST')
AND resource_type = 'OBJECT'
Run Code Online (Sandbox Code Playgroud)
第二个测试,回滚先前的事务,设置 READ_COMMITTED_SNAPSHOT ON 但离开 ALLOW_SNAPSHOT_ISOLATION OFF。
ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO
Run Code Online (Sandbox Code Playgroud)
运行查询 1,然后运行查询 2。DMV 显示查询 1 导致排他锁,但查询 2 返回带有“原始”的详细信息,而没有查询 1 提交事务。READ_COMMITTED 行版本控制似乎已经到位。
添加SET TRANSACTION ISOLATION LEVEL SNAPSHOT;查询 1 和查询 2,并运行查询 1 或查询 2 返回错误 - 快照隔离事务访问数据库 'TEST' 失败,因为该数据库中不允许快照隔离。使用 ALTER DATABASE 允许快照隔离。
第三个测试,回滚之前的事务。设置 READ_COMMITTED_SNAPSHOT OFF 和 ALLOW_SNAPSHOT_ISOLATION ON。
ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO
ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO
Run Code Online (Sandbox Code Playgroud)
运行查询 1,然后运行查询 2。DMV 显示查询 1 引起的排他锁。查询 2 似乎正在等待查询 1 完成。打开 ALLOW_SNAPSHOT_ISOLATION ON 似乎不会启用 READ COMMITTED 行版本控制。
添加SET TRANSACTION ISOLATION LEVEL SNAPSHOT;到查询 1 和查询 2。运行查询 1,然后运行查询 2。虽然 DMV 显示查询 1 导致排他锁,但查询 2 返回带有“原始”的详细信息。快照隔离似乎已经到位。
从测试中观察到,READ_COMMITTED_SNAPSHOT无论ALLOW_SNAPSHOT_ISOLATION设置如何,它本身都会启用/禁用 READ COMMITTED 行版本控制,反之亦然。
小智 7
你的理解是正确的。我喜欢从短,干净,简单的定义在这里:
当 READ_COMMITTED_SNAPSHOT 数据库选项为 ON 时,设置读已提交隔离级别的事务使用行版本控制。
当 ALLOW_SNAPSHOT_ISOLATION 数据库选项为 ON 时,事务可以设置快照隔离级别。
似乎很多误解来自 MS 本身。例如,他们在这里说:
如果将 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON,则数据库引擎默认使用行版本控制和快照隔离,而不是使用锁来保护数据。
但是所提到的“快照隔离”并不等于set transaction isolation level snapshot所应用的事务的行为。
至于区别,这里有很好的解释。
如果 READ_COMMITTED_SNAPSHOT 被命名为 READ_COMMITTED_ROW_VERSIONING 或类似的东西,可能会更好。:)
| 归档时间: |
|
| 查看次数: |
54230 次 |
| 最近记录: |