[转载]SQLSERVER中的元数据锁 – 桦仔 – 博客园.
网上对于元数据锁的资料真的非常少
元数据锁一般会出现在DDL语句里
资源 | 说明 |
RID | 用于锁定堆(heap)中的某一行 |
KEY | 用于锁定索引上的某一行,或者某个索引键 |
PAGE | 锁定数据库中的一个8KB页,例如数据页或索引页 |
EXTENT | 一组连续的8页(区) |
HOBT | 锁定整个堆或B树的锁 |
TABLE | 锁定包括所有数据和索引的整个表 |
FILE | 数据库文件 |
APPLICATION | 应用程序专用的资源 |
METADATA | 元数据锁 |
ALLOCATION_UNIT | 分配单元 |
DATABASE | 整个数据库 |
1 --session 1 2 USE [pratice] 3 GO 4 CREATE TABLE ABC(ID INT) 5 GO 6 7 -------------------------- 8 BEGIN TRAN 9 DROP TABLE ABC 10 --COMMIT TRAN
在会话二里使用元数据函数读取ABC这张表的objectid
1 --session 2 2 USE [pratice] 3 GO 4 --------------------------------------- 5 BEGIN TRAN 6 SELECT OBJECT_ID('ABC') 7 --COMMIT TRAN
这时候就会看到元数据锁,否则就会出问题
我们看一下在session一里面当drop掉表ABC的时候申请了哪些锁
1 USE [pratice] 2 GO 3 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 4 GO 5 6 BEGIN TRAN 7 DROP TABLE ABC 8 9 --COMMIT TRAN 10 11 12 SELECT 13 [request_session_id], 14 c.[program_name], 15 DB_NAME(c.[dbid]) AS dbname, 16 [resource_type], 17 [request_status], 18 [request_mode], 19 [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, 20 p.[index_id] 21 FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p 22 ON a.[resource_associated_entity_id]=p.[hobt_id] 23 LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] 24 WHERE c.[dbid]=DB_ID('pratice') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 25 ORDER BY [request_session_id],[resource_type]
SQLSERVER会锁住一些系统表,例如:syshobts、sysallocunits等,以便对这些系统表进行更新
还有看到SQLSERVER在元数据上加了架构锁
架构锁:数据库引擎在表数据定义语言(DDL)操作(例如添加列或删除表)的过程中使用架构修改(sch-m)锁
以阻止其他用户对这个表格的访问
数据库引擎在编译和执行查询时使用架构稳定(sch-s)锁(稳定stable),sch-s锁不会阻止其他事务访问表格里的数据,但是,
会阻止对表格做修改性的DDL操作和DML操作
这些元数据应该是位于resource数据库中
resource数据库:包含SQLSERVER附带的所有系统对象副本的只读数据库,resource数据库是不能备份的,而且在SSMS里是看不见的
关于resource数据库:SQL Server 2005的Resource数据库
Resource 数据库是只读数据库,它包含了 SQL Server 2005 中的所有系统对象。
SQL Server 系统对象(例如 sys.objects)在物理上存在于 Resource 数据库中,
但在逻辑上,它们出现在每个数据库的 sys 架构中。Resource 数据库不包含用户数据或用户元数据。
当查询某些系统表的时候也会加上元数据锁
1 USE [pratice] 2 GO 3 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 4 GO 5 6 BEGIN TRAN 7 select object_id from sys.tables where name = 'xxx' 8 9 --COMMIT TRAN 10 11 12 SELECT 13 [request_session_id], 14 c.[program_name], 15 DB_NAME(c.[dbid]) AS dbname, 16 [resource_type], 17 [request_status], 18 [request_mode], 19 [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, 20 p.[index_id] 21 FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p 22 ON a.[resource_associated_entity_id]=p.[hobt_id] 23 LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] 24 WHERE c.[dbid]=DB_ID('pratice') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 25 ORDER BY [request_session_id],[resource_type]
令本人不明白的是:在查询时,有时候也会加上元数据锁
建表脚本:
查看申请的锁
1 USE [pratice] 2 GO 3 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 4 GO 5 6 BEGIN TRAN 7 SELECT * FROM ct1 WHERE c1=50 8 9 --COMMIT TRAN 10 11 12 SELECT 13 [request_session_id], 14 c.[program_name], 15 DB_NAME(c.[dbid]) AS dbname, 16 [resource_type], 17 [request_status], 18 [request_mode], 19 [resource_description],OBJECT_NAME(p.[object_id]) AS objectname, 20 p.[index_id] 21 FROM sys.[dm_tran_locks] AS a LEFT JOIN sys.[partitions] AS p 22 ON a.[resource_associated_entity_id]=p.[hobt_id] 23 LEFT JOIN sys.[sysprocesses] AS c ON a.[request_session_id]=c.[spid] 24 WHERE c.[dbid]=DB_ID('pratice') AND a.[request_session_id]=@@SPID ----要查询申请锁的数据库 25 ORDER BY [request_session_id],[resource_type]
但是在SQLSERVER2012中
无论是
BEGIN TRAN
select object_id from sys.tables with (nolock) where name = ‘xxx’
还是
BEGIN TRAN
SELECT * FROM ct1 WHERE c1=50
都看不到元数据锁了
1 BEGIN TRAN 2 select object_id from sys.tables with (nolock) where name = 'xxx'
1 BEGIN TRAN 2 select object_id from sys.tables with (nolock) where name = 'xxx'
可能SQLSERVER2012隐藏了元数据锁,觉得就算显示出元数据锁对于排查阻塞也没有多大意义,干脆隐藏算了
但是这里并不是说SQLSERVER2012没有了元数据锁
元数据是一种资源,可以锁定的资源,元数据锁并不是一种锁类型!!!
相关文章:
http://social.msdn.microsoft.com/Forums/zh-CN/10c07757-741d-4473-888c-174c9c91f038
http://social.msdn.microsoft.com/Forums/zh-CN/c5c20bed-3fb7-414e-ade5-fb70c532cd84
http://msdn.microsoft.com/zh-cn/library/ms187812(v=sql.105).aspx