网上对于元数据锁的资料真的非常少

元数据锁一般会出现在DDL语句里

下面列出数据库引擎可以锁定的资源

资源 

说明

RID

用于锁定堆(heap)中的某一行

KEY

用于锁定索引上的某一行,或者某个索引键

PAGE 

锁定数据库中的一个8KB页,例如数据页或索引页

EXTENT

一组连续的8页(区)

HOBT

锁定整个堆或B树的锁

TABLE 

锁定包括所有数据和索引的整个表

FILE

数据库文件

APPLICATION 

应用程序专用的资源

METADATA   

元数据锁

ALLOCATION_UNIT  

分配单元

DATABASE

整个数据库

 
锁住元数据的目的跟其他的锁是一样的,都是保证事务的一致性
 
实验环境:SQLSERVER2005 ,SQLSERVER2012,如果没有特别说明的话,SQL语句都是在SQLSERVER2005上运行
 
例如,在会话一里drop掉ABC表
 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中的元数据锁

SQLSERVER中的元数据锁

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]

SQLSERVER中的元数据锁


令本人不明白的是:在查询时,有时候也会加上元数据锁

建表脚本:

 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

相关文章:

  • 2022-12-23
  • 2021-06-26
  • 2021-10-15
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-15
猜你喜欢
  • 2022-12-23
  • 2021-07-08
  • 2021-06-03
  • 2021-08-19
  • 2021-07-06
  • 2021-08-14
相关资源
相似解决方案