SQLSERVER中的元数据锁
网上对于元数据锁的资料真的非常少
元数据锁一般会出现在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会锁住一些
系统表,例如:syshobts、sysallocunits等,以便对这些系统表进行更新
还有看到SQLSERVER在元数据上加了架构锁
架构锁:数据库引擎在表数据定义语言(DDL)操作(例如添加列或删除表)的过程中使用架构修改(sch-m)锁
以阻止其他用户对这个表格的访问
数据库引擎在编译和执行查询时使用架构稳定(sch-s)锁(稳定stable),sch-s锁不会阻止其他事务访问表格里的数据,但是,
会阻止对表格做修改性的DDL操作和DML操作
这些元数据应该是位于resource数据库中
resource数据库:包含SQLSERVER附带的所有系统对象副本的只读数据库,resource数据库是不能备份的,而且在SSMS里是看不见的
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]
令本人不明白的是:在查询时,有时候也会加上元数据锁
建表脚本:
查看申请的锁