Mic*_*een 5 sql-server sql-server-2008-r2 rollback locking
通常,SQL Server 会在更新期间获取锁。它还支持锁升级:
锁升级是将许多细粒度锁转换为较少粗粒度锁的过程,减少系统开销的同时增加并发争用的概率。
在事务 ROLLBACK 期间,SQL Server 是否会降级锁,放回细粒度锁?
Mic*_*een 10
SQL Server 不会降级锁定。
我使用具有 100,000 行的“ Numbers ”表进行了调查。根据经验,更新 5,000 行会在sys.dm_tran_locks. 再更新 10,000 行导致升级为单个表锁。这始终是可重现的。为了最小化所涉及的对象,该表是一个没有索引的堆。
我使用扩展事件跟踪来捕获lock_acquired和lock_released事件。为了便于分析,我在 UPDATE 和 ROLLBACK 阶段使用了单独的跟踪。
使用了两个会话(SSMS 窗口)——一个用于 DML 语句,另一个用于跟踪 DDL。我无法使用单个会话,因为我想在事务打开时停止和启动跟踪,这是不允许的。隔离级别始终为 READCOMITTED。
结果select @@VERSION是
Microsoft SQL Server 2008 R2 (SP2) - 10.50.4042.0 (Intel X86) 2015 年 3 月 26 日 21:49:16 版权所有 (c) Microsoft Corporation Enterprise Edition on Windows NT 6.1(Build 7601:Service Pack 1)
采取的步骤是
创建并启动获取跟踪。
CREATE EVENT SESSION DuringUpdate
ON SERVER
ADD EVENT sqlserver.lock_acquired,
ADD EVENT sqlserver.lock_released
ADD TARGET package0.asynchronous_file_target
(SET filename = 'c:\temp\LockRollback\DuringUpdate.xel',
metadatafile = 'c:\temp\LockRollback\DuringUpdate.xem')
WITH(EVENT_RETENTION_MODE = NO_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 1 SECONDS
);
ALTER EVENT SESSION DuringUpdate
ON SERVER
STATE = start;
Run Code Online (Sandbox Code Playgroud)开始一个事务并更新 5000 行。
begin transaction;
update dbo.Numbers
set Number = Number
where Number between 1 and 5000;
Run Code Online (Sandbox Code Playgroud)再更新 10000 行。
update dbo.Numbers
set Number = Number
where Number between 5001 and 15000;
Run Code Online (Sandbox Code Playgroud)停止获取跟踪。
ALTER EVENT SESSION DuringUpdate
ON SERVER
STATE = stop;
Run Code Online (Sandbox Code Playgroud)通过查询sys.dm_tran_locks(2 - DB, table)验证是否有锁。
创建并启动发布跟踪。
CREATE EVENT SESSION DuringRollback
ON SERVER
ADD EVENT sqlserver.lock_acquired,
ADD EVENT sqlserver.lock_released
ADD TARGET package0.asynchronous_file_target
(SET filename = 'c:\temp\LockRollback\DuringRollback.xel',
metadatafile = 'c:\temp\LockRollback\DuringRollback.xem')
WITH(EVENT_RETENTION_MODE = NO_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 1 SECONDS
);
ALTER EVENT SESSION DuringRollback
ON SERVER
STATE = start;
Run Code Online (Sandbox Code Playgroud)回滚事务。
rollback;
Run Code Online (Sandbox Code Playgroud)停止发布跟踪。
ALTER EVENT SESSION DuringRollback
ON SERVER
STATE = stop;
Run Code Online (Sandbox Code Playgroud)整理
DROP EVENT SESSION DuringUpdate
ON SERVER;
DROP EVENT SESSION DuringRollback
ON SERVER;
Run Code Online (Sandbox Code Playgroud)如果发生锁降级,我希望在两个跟踪文件中完全对称 - 在 UPDATE 和升级期间获取的每个锁在 ROLLBACK 期间都会有相应的释放。我观察到的:
SELECT
COUNT(*) as DuringUpdate
FROM sys.fn_xe_file_target_read_file(
'c:\temp\LockRollback\DuringUpdate*.xel',
'c:\temp\LockRollback\DuringUpdate*.xem', null, null);
SELECT
COUNT(*) as DuringRollback
FROM sys.fn_xe_file_target_read_file(
'c:\temp\LockRollback\DuringRollback*.xel',
'c:\temp\LockRollback\DuringRollback*.xem', null, null);
Run Code Online (Sandbox Code Playgroud)
分别为 383,889 行和 166 行。检查回滚文件的事件 XML,只有一个与 RID、PAGE 或 OBJECTS 相关的事件 - 表上的 X 锁的释放。我由此得出结论,在回滚期间锁没有降级。
这与回滚到命名保存点的文档相呼应:
指定 savepoint_name 的 ROLLBACK TRANSACTION 语句会释放在保存点之外获取的任何锁,升级和转换除外。这些锁不会被释放,也不会转换回它们之前的锁模式。
| 归档时间: |
|
| 查看次数: |
784 次 |
| 最近记录: |