SET NOCOUNT ON;
DECLARE @Query nvarchar(max) =
N'DECLARE @C INT;
SELECT @C = COUNT(*) FROM master.dbo.MSreplication_options';
/*Run once so compilation out of the way*/
EXEC(@Query);
DBCC TRACEON(-1,3604,1200) WITH NO_INFOMSGS;
PRINT 'READ UNCOMMITTED';
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
EXEC(@Query);
PRINT 'READ COMMITTED';
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
EXEC(@Query);
DBCC TRACEOFF(-1,3604,1200) WITH NO_INFOMSGS;
输出 READ UNCOMMITTED
Process 56 acquiring Sch-S lock on OBJECT: 1:1163151189:0 (class bit0 ref1) result: OK
Process 56 acquiring S lock on HOBT: 1:72057594038910976 [BULK_OPERATION] (class bit0 ref1) result: OK
Process 56 releasing lock on OBJECT: 1:1163151189:0
输出 READ COMMITTED
Process 56 acquiring IS lock on OBJECT: 1:1163151189:0 (class bit0 ref1) result: OK
Process 56 acquiring IS lock on PAGE: 1:1:169 (class bit0 ref1) result: OK
Process 56 releasing lock on PAGE: 1:1:169
Process 56 releasing lock on OBJECT: 1:1163151189:0
根据引用保罗·兰达尔的这篇文章,采取BULK_OPERATION共享HOBT锁的原因是为了防止读取未格式化的页面。
ReadUncommitted隔离级别确实会获取锁。模式稳定性锁在查询执行期间防止被查询的对象被修改。这些锁在所有隔离级别下都会被获取,包括快照和读取已提交的快照(RCSI)。来自锁模式:
模式锁
数据库引擎在表数据定义语言(DDL)操作期间使用模式修改(Sch-M)锁,例如添加列或删除表。在持有该锁的时间内,Sch-M锁阻止对表的并发访问。这意味着Sch-M锁会阻塞所有外部操作,直到释放锁为止。
某些数据操作语言(DML)操作,例如表截断,使用Sch-M锁来防止并发操作对受影响的表的访问。
数据库引擎在编译和执行查询时使用模式稳定性(Sch-S)锁。Sch-S锁不会阻塞任何事务锁,包括排他(X)锁。因此,在查询编译期间,其他具有表上X锁的事务仍然可以运行。但是,无法对表执行并发的DDL操作和获取Sch-M锁的并发DML操作。