sql - 快照隔离行为。第一次查询时为 "Triggered"?

标签 sql sql-server tsql isolation-level snapshot-isolation

我正在做一些测试,试图了解快照隔离是如何工作的……但我没有。我的数据库中有 SET ALLOW_SNAPSHOT_ISOLATION ON(对 READ_COMMITTED_SNAPSHOT atm 不感兴趣)。然后我做了以下测试。我将通过 [s1] 和 [s2] 标记来标记不同的 session (实际上是我的 ssms 中的不同选项卡),[s2] 是隔离 session ,[s1] 模拟另一个非隔离 session 。

首先,创建一个表格,然后给它一行。 @[s1]:

create table _g1 (v int)
insert _g1 select 1
select * from _g1
(Output: 1)

现在让我们开始一个独立的事务。 @[s2]:

set transaction isolation level snapshot
begin tran

插入另一行,@[s1]:

insert _g1 select 2

现在让我们看看隔离事务“看到”了什么,@[s2]:

select * from _g1
(Output: 1,2)

奇怪。难道隔离不应该从“Begin tran”那一刻起就“开始计数”吗?在这里,它不应该返回 2...让我们再做一次。 @[s1]:

insert _g1 select 3

@[s2]:

select * from _g1
(Output: 1,2)

所以,这次它按我的预期工作,并且没有考虑最新的插入。

如何解释这种行为?隔离是否在每个表第一次访问后开始起作用?

最佳答案

快照隔离与行版本控制一起使用。对于行上的每次修改,数据库引擎都会维护该行的先前版本和当前版本,以及进行修改的事务的序列号 (XSN)。

当快照隔离用于[s2]中的事务时:

The Database Engine reads a row within the transaction and retrieves the row version from tempdb whose sequence number is closest to, and lower than, the transaction sequence number.

(请参阅 https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server 中的“快照隔离和行版本控制如何工作”)。在发出 DML 语句之前,[s2] 中的事务的事务序列号 XSN2 不会被分配。

sys.dm_tran_active_snapshot_database_transactions 是一个返回虚拟表的 DMV 对于生成或可能访问行版本的所有事件事务。您可以查询此 View 以获取有关访问行版本的事件事务的信息。

要验证上述所有内容,您可以尝试:

@[s1]

create table _g1 (v int)

@[s2]

set transaction isolation level snapshot
begin tran

select * from sys.dm_tran_active_snapshot_database_transactions  -- < No XSN has been assigned, yet. Zero rows are returned.

select * from _g1 --< XSN2 is now assigned.
(Output: zero rows)

select * from sys.dm_tran_active_snapshot_database_transactions  -- < XSN2 has been assigned and the corresponding record is returned.

@[s1]

insert _g1 select 1
select * from _g1
(Output: 1)

@[s2]

select * from _g1
(Output: zero rows)

请参阅 https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-active-snapshot-database-transactions-transact-sql?view=sql-server-ver15 中的备注关于何时发出 XSN:

sys.dm_tran_active_snapshot_database_transactions reports transactions that are assigned a transaction sequence number (XSN). The XSN is assigned when the transaction first accesses the version store. In a database that is enabled for snapshot isolation or read committed isolation using row versioning, the examples show when an XSN is assigned to a transaction:

  • If a transaction is running under serializable isolation level, an XSN is assigned when the transaction first executes a statement, such as an UPDATE operation, that causes a row version to be created.

  • If a transaction is running under snapshot isolation, an XSN is assigned when any data manipulation language (DML) statement, including a SELECT operation, is executed.

因此,为了回答您的问题,快照隔离在事务中发出第一个“SELECT”或其他 DML 语句之后“开始计数”,而不是在“开始事务”语句之后立即“开始计数”。

关于sql - 快照隔离行为。第一次查询时为 "Triggered"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58910223/

相关文章:

sql-server-2005 - 从另一个存储过程调用一个存储过程

mysql - MySQL 8.x 中的主要错误? -- 外键

sql - 如何让BCP生成用于将固定宽度数据导入SQL Server表的格式文件?

SQL Server - 如何管理表中的分层数据?

sql - 如何在 MS SQL 2005 中使用 SQL XQuery 修改多个节点

c# - Linq 日期区分为字符串 yyyy-mm-dd

sql - 如何使用窗口函数获取最高价格及其 ID?

SQL 根据日期键求和列

php - 如何使用多个 HTML 文本输入进行 SQL 搜索查询

sql-server - 将父表列值附加到sql中的子表列