1

我在学习 SQL Server 中的事务隔离级别时遇到了一个问题。

问题是,在我运行这段代码之后(并且它没有错误地完成):

set implicit_transactions off;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN T1;

SELECT (...)
WAITFOR DELAY '00:00:5' 
SELECT (...)
WAITFOR DELAY '00:00:3' 

COMMIT TRAN T1;

我想运行这个查询:

set implicit_transactions off;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRANSACTION T2;

INSERT (...)
INSERT (...)

COMMIT TRANSACTION T2;

但它只是说“执行查询”,什么都不做。我认为这是因为在第一个事务完成后,表上的锁以某种方式继续存在。有人可以帮忙吗?当然,选择和插入指的是同一个表。

4

3 回答 3

2

第一个 tran 仍然打开(关闭窗口以确保它没有打开),或者其他一些 tran 是打开的 ( exec sp_who2)。您不能禁止 DML 使用 X 锁,因为 SQL Server 在回滚期间需要这些锁。

于 2014-01-12T20:42:10.050 回答
0

@usr 提供了很好的可能性。

一个相关的具体可能性是您在修补时只选择了第一个事务的一部分来执行 - 即执行但BEGIN TRAN T1从未执行COMMIT TRAN T1。它发生了——我认为是墨菲定律的一部分。尝试执行 just COMMIT TRAN T1,然后重新尝试第二个片段。

在单个会话中重复完整的执行时,以下内容对我来说效果很好:

set implicit_transactions off;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN T1;

SELECT * from tbl_A
WAITFOR DELAY '00:00:5' 
SELECT * from tbl_B
WAITFOR DELAY '00:00:3' 

COMMIT TRAN T1;


set implicit_transactions off;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRANSACTION T2;

INSERT tbl_A (ModifiedDate) values (GETDATE())
INSERT tbl_B (ModifiedDate) values (GETDATE())
INSERT tbl_A (ModifiedDate) select top 1 ModifiedDate from tbl_A
INSERT tbl_B (ModifiedDate) select top 1 ModifiedDate from tbl_B

COMMIT TRANSACTION T2;
于 2014-01-12T20:47:37.710 回答
0

1 - SET IMPLICT_TRANSACTIONS 通常为 OFF,除非您将 ANSI_DEFAULTS 设置为 ON。然后它将打开。因此,如果不需要,您可以删除这个额外的语句。

2 - 我同意亚伦。读取未提交(无锁)应与 SELECT 语句一起使用。但是,这可能会导致无效的结果。它容易丢失数据、两次读取数据或扫描错误。

Read Committed Snap Shot Isolation (RCSI) 是一个更好的选择,但会牺牲 tempdb(版本存储空间)。这将使您的报告(读者)不会被交易(作者)阻止。

3 - 设置,SET TRANSACTION ISOLATION LEVEL SERIALIZABLE,将使用最多数量的锁。因此,增加阻塞的机会。

为什么将这种低并发隔离级别与两个 INSERT 语句一起使用?

我可以理解使用这个级别来更新多个表。例如,银行交易。借记一行,贷记另一行。两张桌子。在交易完成之前,没有人可以访问记录。

简而言之,我会为插入语句使用 READ COMMITTED 隔离级别。插入的数据很可能是不同的。

然而,整个画面并不在这里。

正在发生某种类型的阻塞。你需要找到根本原因。

这是查看锁和被锁定对象的代码片段。

--
-- Locked object details
-- 

-- Old school technique
EXEC sp_lock
GO

-- Lock details
SELECT
    resource_type, resource_associated_entity_id,
    request_status, request_mode,request_session_id,
    resource_description 
    FROM sys.dm_tran_locks
    WHERE resource_database_id = DB_ID('AdventureWorks2012')
GO

-- Page/Key details
SELECT object_name(object_id) as object_nm, *
    FROM sys.partitions
    WHERE hobt_id = 72057594047037440
GO

-- Object details
SELECT object_name(1266103551)
GO

如果您仍然需要帮助,请识别两个阻塞事务和锁。请张贴此信息。

于 2014-01-13T01:03:01.913 回答