SQL Server - 在事务回滚期间我有什么访问权限?

Ngo*_*vin 3 sql-server rollback locking

正如标题所说,在回滚事务时,我是否对整个数据库具有读/写访问权限?

或者仅对事务未写入的表进行读/写访问?什么是锁定行为?

如果我有读访问权限,当我读取事务回滚写入的表时会发生什么(查询失败还是等待)?

抱歉,我曾尝试在线阅读(ROLLBACK TRANSACTION (Transact-SQL)),但似乎没有触及这种深度。

AMt*_*two 5

答案在很大程度上取决于您的隔离级别、被回滚的事务持有什么类型的锁,以及您的非回滚会话试图做什么。

步骤 1)什么是锁定的?

ROLLBACK发出之前,该事务已经完成工作并获得了锁。您可以通过查看这些锁的详细信息sys.dm_tran_locks

SELECT tl.resource_type, tl.resource_associated_entity_id,
       tl.request_status, tl.request_mode, tl.request_session_id,
       tl.resource_description
FROM sys.dm_tran_locks tl
WHERE tl.request_session_id = <ROLLBACK session id>;
Run Code Online (Sandbox Code Playgroud)

resource_typeresource_associated_entity_id会告诉你什么是锁定的。如果resource_type是“对象”,则resource_associated_entity_idobject_id. 如果resource_type是“Key”或“Page”,则resource_associated_entity_idhobt_id. 有更多类型需要解码,但这两种类型涵盖了大多数场景。

SELECT tl.resource_type, tl.resource_associated_entity_id,tl.resource_database_id,
       CASE WHEN resource_type = 'OBJECT' 
                THEN object_name(tl.resource_associated_entity_id,tl.resource_database_id)
            WHEN resource_type IN ('KEY','PAGE')
                THEN object_name(p.object_id)
        END AS resource_name,
       tl.request_status, tl.request_mode, tl.request_session_id,
       tl.resource_description
FROM sys.dm_tran_locks tl
LEFT JOIN sys.partitions p ON p.hobt_id = tl.resource_associated_entity_id
                           AND tl.resource_database_id = db_id()
WHERE tl.request_session_id = <ROLLBACK session id>;
Run Code Online (Sandbox Code Playgroud)

最后,锁定模式提供有关如何使用该锁定的信息。BOL列出了所有不同的锁定模式。

第 2 步:什么会被阻止?

如果被回滚的事务没有锁定对象,则ROLLBACK不会阻塞其他会话。那部分很容易。

这些锁是否会导致阻塞将取决于您的隔离级别以及您尝试执行的操作。Paul White有一个关于隔离级别的非常深入的系列,您可以阅读其中的许多详细信息。

读取、写入和隔离级别的不同组合将产生不同的阻塞结果。一般来说,写总是阻塞写。但是,写入可能会也可能不会阻止读取。在 SQL Server 的默认READ_COMMITTED隔离级别下,写入将阻止读取。如果您正在使用READ_COMMITTED_SNAPSHOT(又名“RCSI”又名“使用行版本控制的读取提交”),则写​​入不会阻止读取。

在所有情况下,如果另一个会话被 中的会话阻塞ROLLBACK,等待的会话将等待直到ROLLBACK释放锁。