设置ALLOW_SNAPSHOT_ISOLATION的含义是什么?

时间:2010-11-06 02:55:22

标签: sql-server database database-design concurrency performance

我应该跑吗

ALTER DATABASE DbName SET ALLOW_SNAPSHOT_ISOLATION OFF

是否暂时使用快照事务(TX)隔离(iso)? 换句话说,

  • 为什么要首先启用?
  • 为什么默认情况下不启用?

在SQL Server中启用(但暂时不使用)的成本是多少?


- 更新:
在数据库上启用快照TX iso级别不会将READ COMMITTED tx iso更改为默认值 您可以通过运行来检查它:

use someDbName;
--( 1 )
alter database someDbName set allow_snapshot_isolation ON;
dbcc useroptions;

最后一行显示当前会话的tx iso级别为(读取已提交)。

因此,启用快照tx iso级别而不更改它不会使用它等 为了使用它,应该发出

--( 2 )
SET TRANSACTION ISOLATION LEVEL SNAPSHOT

UPDATE2:
我重复[1]中的脚本,但启用了SNAPSHOT(但没有打开)但没有启用READ_COMMITTED_SNAPSHOT

--with enabling allow_snapshot_isolation
alter database snapshottest set allow_snapshot_isolation ON

-- but without enabling read_committed_snapshot
--alter database snapshottest set read_committed_snapshot ON
-- OR with OFF
alter database snapshottest set read_committed_snapshot OFF 
go

执行

时没有结果/行
select * from sys.dm_tran_version_store

执行INSERT,DELETE或UPDATE

你能给我提供一些脚本,说明通过(1)启用SNAPSHOT tx iso级别但是没有打开(2)会在tempdb中生成任何版本和/或增加每行14个字节的数据大小吗? 真的,我不明白版本控制的重点是,如果它是由(1)启用但未使用(未由(2)设置)?

[1]
在SQL Server中管理TempDB:TempDB基础知识(版本存储:简单示例)
http://blogs.msdn.com/b/sqlserverstorageengine/archive/2008/12/31/managing-tempdb-in-sql-server-tempdb-basics-version-store-simple-example.aspx

2 个答案:

答案 0 :(得分:21)

只要在数据库中启用了行版本控制(又称快照),就必须对所有写入进行版本控制。在写入发生的隔离级别下无关紧要,因为隔离级别总是影响读取。一旦启用了数据库行版本控制,任何插入/更新/删除都将:

  • 每行增加14个字节的数据大小
  • 可能在版本存储(tempdb)
  • 中的更新之前创建数据的映像

同样,使用什么隔离级别完全无关紧要。请注意,如果满足以下任何条件,则也会发生行版本控制:

  • 表有一个触发器
  • 已在连接上启用MARS
  • 表格上正在运行在线索引操作

所有这些都在Row Versioning Resource Usage中解释:

  

每个数据库行最多可使用14个   行末尾的字节数   版本信息。排   版本信息包含   交易序列号   提交版本的事务   和指向版本化行的指针。   这14个字节是第一个添加的   修改行的时间,或者   在 任意 下插入新行   这些条件:

     
      
  • READ_COMMITTED_SNAPSHOT或ALLOW_SNAPSHOT_ISOLATION选项   ON。
  •   
  • 该表有一个触发器。
  •   
  • 正在使用多个活动结果集(MARS)。
  •   
  • 目前正在桌面上运行在线索引构建操作。
  •   
     

...

     

必须存储行版本   只要活动交易需要   访问它。 ...如果它符合 任何   以下条件:

     
      
  • 它使用基于行版本控制的隔离。
  •   
  • 它使用触发器,MARS或在线索引构建操作。
  •   
  • 它会生成行版本。
  •   

<强>更新

:setvar dbname testsnapshot

use master;

if db_id('$(dbname)') is not null
begin
    alter database [$(dbname)] set single_user with rollback immediate;
    drop database [$(dbname)];
end
go

create database [$(dbname)];
go

use [$(dbname)];
go


-- create a table before row versioning is enabled
--
create table t1 (i int not null);
go
insert into t1(i) values (1);
go

-- this check will show that the records do not contain a version number
--
select avg_record_size_in_bytes 
from sys.dm_db_index_physical_stats (db_id(), object_id('t1'), NULL, NULL, 'DETAILED')
-- record size: 11 (lacks version info that is at least 14 bytes)


-- enable row versioning and and create an identical table
--
alter database [$(dbname)] set allow_snapshot_isolation on;
go

create table t2 (i int not null);
go

set transaction isolation level read committed;
go

insert into t2(i) values (1);
go

-- This check shows that the rows in t2 have version number
--
select avg_record_size_in_bytes
     from sys.dm_db_index_physical_stats (db_id(), object_id('t2'), NULL, NULL, 'DETAILED')
-- record size: 25 (11+14)

-- this update will show that the version store has records
-- even though the isolation level is read commited
--
begin transaction;
update t1 
    set i += 1; 
select * from sys.dm_tran_version_store;
commit;
go

-- And if we check again the row size of t1, its rows now have a version number
select avg_record_size_in_bytes
from sys.dm_db_index_physical_stats (db_id(), object_id('t1'), NULL, NULL, 'DETAILED')
-- record size: 25

答案 1 :(得分:1)

默认情况下,您将快照隔离关闭,如果将其打开,SQL将维护用于运行事务的数据快照。 示例:在连接1上,您正在运行大选择。在连接2上,您将更新将首先选择返回的一些记录。

在快照隔离开启时,SQL将生成受更新影响的数据的临时副本,因此SELECT将返回原始数据。

任何其他数据操作都会影响性能。这就是默认情况下此设置为OFF的原因。