纷纭教育
您的当前位置:首页SQLSERVER中的元数据锁

SQLSERVER中的元数据锁

来源:纷纭教育


当查询某些系统表的时候也会加上元数据锁

 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 --建表
 4 CREATE TABLE ct1(c1 INT,c2 INT, c3 VARCHAR (2000));
 5 GO
 6 --建立聚集索引
 7 CREATE CLUSTERED INDEX t1c1 ON ct1(c1);
 8 GO
 9 
10 --建立非聚集索引
11 CREATE INDEX nt1c1 ON ct1(c2);
12 GO 
13 
14 
15 --插入测试数据
16 DECLARE @a INT;
17 SELECT @a = 1;
18 WHILE (@a <= 1000)
19 BEGIN
20 INSERT INTO ct1 VALUES (@a,@a, replicate('a', 2000))
21 SELECT @a = @a + 1
22 END
23 GO
24 
25 
26 
27 
28 --查询数据
29 SELECT * FROM ct1 

View Code

查看申请的锁

 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

如有不对的地方,欢迎大家拍砖o(∩_∩)o

2014-8-9修正

SQLSERVER也有像ORACLE数据字典的概念,实际上无论哪一种数据库都有数据字典,只是叫法不同,而sqlserver的数据字典叫元数据而不叫数据字典

mysql 的innodb引擎表会把数据字典存放ibdata共享表空间里

SQLSERVER会把数据字典存放在主文件组

ORACLE会把数据字典存放在system表空间

sqlserver里面的syshobts、sysallocunits表都是带sys开头的,都是数据字典

数据字典含义:描述数据的数据

记录了用户数据库中的各个表的表名、字段名、索引信息、表记录数等等相关信息

所以修改表数据的时候也会修改相应的数据字典表,所以sqlserver就要锁元数据

实际上无论数据字典还是元数据,实际上就是一张张的表,我们叫系统基本,一般我们是不能操作的,数据库会利用系统视图来对

这些系统基表进行封装屏蔽,例如sqlserver里的sys.[syscolumns]视图,oracle里面的数据字典视图,例如以x$ 开头的静态数据字典视图和

v$开头的动态数据字典视图(v$database)

文章中的错误:这些元数据应该是位于resource数据库中

这些元数据是各自存放在用户库里的,在创建数据库的时候先从resource数据库里把这些系统视图和系统基表结构从resource数据库里拷贝过来

再从model数据库里拷贝一些存储过程、函数和数据库参数,在这里resource数据库和model数据库其实就是创建时候充当模版的角色

而这些系统视图和系统基表都是以为sys开头的sys 架构

由于有时候修改表数据的时候也会顺带修改这些系统基表,所以大家也会看到sqlserver申请了元数据锁

当数据库启动的时候,你没有任何操作,然后关闭数据库,可以通过开启sqlserver实例和关闭sqlserver实例来测试

你会看到ldf文件里会记录修改系统基表的操作,即使你什么操作也没有做

显示全文