网上对于元数据锁的资料真的非常少
元数据锁一般会出现在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 --建表 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