Sql-Server
全域臨時表上持有哪些類型的鎖?
我想知道是否:
- 隔離級別為已送出讀
- 數據被插入、刪除或讀取
與傳統的行儲存表一樣,用於全域臨時表的鎖是相同的鎖(讀取共享,插入/刪除獨占)。
對於臨時表,我相信它在目前上下文中“存在”時不會發生阻塞,因此我無法同時讀取和插入數據。
但是對於全域臨時表,假設我有很多操作——一些正在插入新數據,一些正在刪除數據,還有一些要讀取的數據將被刪除。
假設表的結構是:
GroupID EntityID 1 101 1 102 1 103 2 101 2 104 3 100
這裡是否適用相同的規則?
我對這個問題很好奇,想試試看 tempdb 是一個特殊的數據庫,還是就像另一個使用者數據庫一樣,其中應用了預設隔離“已送出讀”。
以下是我執行的查詢:
--Created two tables in tempdb, one named table and second one as gobal tempdb table select * into tempdb.dbo.msgs from sys.messages select * into ##msgs from sys.messages
在下一個視窗中對這些表的幾條記錄執行更新查詢
begin tran go update dbo.msgs set language_id = 1055 where message_id = 11242 go update ##msgs set language_id = 1055 where message_id = 11242 go
上述兩個語句都按預期更新了 22 行。
後來我在兩個不同的視窗中對這兩個表執行了 select 語句,到目前為止都被卡住了:
我注意到在第一個查詢中根本沒有任何記錄出現在螢幕上,而在第二種情況下,8830 條記錄在螢幕上並隨後卡住(不知道為什麼?)但是在這兩種情況下,查詢都被卡住並永遠執行他們正在等待更新完成。這是 MSSQL 數據庫的預設行為所期望的。
我使用 sp_whoisactive 進行了驗證,並且可以看到存在如下數據庫阻塞:
詳細資訊提供了它們中的每一個的鎖定資訊。
第一個:
<Database name="tempdb"> <Objects> <Object name="msgs" schema_name="dbo"> <Locks> <Lock resource_type="OBJECT" request_mode="IS" request_status="GRANT" request_count="1" /> <Lock resource_type="PAGE" page_type="*" request_mode="S" request_status="WAIT" request_count="1" /> </Locks> </Object> </Objects> </Database>
第二:
<Database name="tempdb"> <Objects> <Object name="##msgs" schema_name="dbo"> <Locks> <Lock resource_type="OBJECT" request_mode="IX" request_status="GRANT" request_count="1" /> <Lock resource_type="PAGE" page_type="*" request_mode="UIX" request_status="GRANT" request_count="22" /> <Lock resource_type="RID" page_type="*" request_mode="X" request_status="GRANT" request_count="22" /> </Locks> </Object> <Object name="msgs" schema_name="dbo"> <Locks> <Lock resource_type="OBJECT" request_mode="IX" request_status="GRANT" request_count="1" /> <Lock resource_type="PAGE" page_type="*" request_mode="UIX" request_status="GRANT" request_count="22" /> <Lock resource_type="RID" page_type="*" request_mode="X" request_status="GRANT" request_count="22" /> </Locks> </Object> </Objects> </Database>
第三:
<Database name="tempdb"> <Objects> <Object name="##msgs" schema_name="dbo"> <Locks> <Lock resource_type="OBJECT" request_mode="IS" request_status="GRANT" request_count="1" /> <Lock resource_type="PAGE" page_type="*" request_mode="S" request_status="WAIT" request_count="1" /> </Locks> </Object> </Objects> </Database>
還使用以下命令交叉檢查每個事務的隔離級別:
SELECT CASE transaction_isolation_level WHEN 0 THEN 'Unspecified' WHEN 1 THEN 'ReadUncommitted' WHEN 2 THEN 'ReadCommitted' WHEN 3 THEN 'Repeatable' WHEN 4 THEN 'Serializable' WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL FROM sys.dm_exec_sessions where session_id in(63,66,67)
結果:
有了所有這些,可以說對於 tempdb,隔離級別也設置為“已送出讀”,並且規則適用於其他數據庫。
我已經在 MSSQL 2019 版本上執行了這些查詢。