網上對於元數據鎖的資料真的很是少html
元數據鎖通常會出如今DDL語句裏mysql
資源 web |
說明sql |
RID數據庫 |
用於鎖定堆(heap)中的某一行session |
KEY架構 |
用於鎖定索引上的某一行,或者某個索引鍵oracle |
PAGE ide |
鎖定數據庫中的一個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
查看申請的鎖
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文件裏會記錄修改系統基表的操做,即便你什麼操做也沒有作