2013-11-15 55 views
1

實驗細節:爲什麼objectID(N'tablename')不鎖定並且name ='tablename'鎖定sys.objects?

我在Microsoft SQL Server Management Studio中運行此。 在一個查詢窗口,我跑:

BEGIN TRANSACTION a; 
     ALTER table <table name> 
      ALTER column <column> varchar(1025) 

另外我運行:

SELECT 1 
     FROM sys.objects 
     WHERE name = ' <other_table name>' 

或者這樣:

SELECT 1 
     FROM sys.objects 
     WHERE object_id = OBJECT_ID(N'[<other_table name>]') 

出於某種原因與名稱選擇=不返回,直到我確實承諾傳遞。

我做交易,以模擬ALTER列的長時間操作,我們已經在我們的數據庫的時候。我不想傷害其他行動。

+1

如果你看看兩者的實際執行計劃,你應該看到'name'變體在非聚集索引和單獨的查找步驟上使用seek。而object_id變體只是執行聚集索引查找。我還會注意到,該交易似乎對某些密鑰持有一些排他鎖。我還沒有設法構建一個完整的理論(因此評論不答覆),但我認爲它可能涉及到第一個查詢可能不得不掃描範圍(因爲重複的名稱是可能的)。不幸的是,'OBJECT_ID'是一個黑盒子,所以不清楚它爲什麼沒有鎖定就可以工作。 –

回答

0

這是因爲你下的默認事務隔離級別即ReadCommited工作。
讀取已提交
在您明確開始事務時讀取已提交的傳送隔離級別Sql Server獲取對資源的獨佔鎖定以維護數據完整性並防止用戶進行髒讀。一旦你開始了一個事務並且處理了一些行,其他用戶將無法看到它們直到你提交事務或回滾。但是,這是sql server的默認行爲,這可以在不同的事務隔離級別下進行更改,例如在Read Uncommited下您可以讀取其他用戶正在修改/使用的行,但是您可能有髒讀「數據你認爲還在數據庫中,但其他用戶已經改變了它。「
我的建議
如果髒讀的東西,你可以去住不是

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED; 

最好,否則堅持到SQL Server默認的行爲,並讓用戶等待了一下,而不是讓他們髒/錯誤的數據。我希望它有幫助。
編輯

如果這兩個查詢都在相同或不同的隔離級別重要的是根據正在執行什麼隔離級別的查詢執行沒關係,你必須有讀未提交的事務隔離級別時您正在使用明確的交易。如果您希望其他用戶在交易過程中訪問數據。沒有推薦和一個不好的做法,我會親自使用快照隔離,這將廣泛使用tempdb,並將只顯示最後提交的數據。

+0

但是兩個查詢都以相同的隔離級別運行,仍然有一個查詢需要我添加READ UNCOMMITED,另一個不。這是確切的問題。 – Zamir

+0

請參閱我的更新的答案進一步解釋。 thankyou –

+1

請重新閱讀OP的問題。他們有3段代碼。將這三部分放到3個獨立的查詢窗口中,連接到同一個數據庫,並創建/修改適當的表名和列名。運行第一塊。如果你切換到第二塊並嘗試運行它,它會阻塞。如果切換到第三塊並嘗試運行它,它運行良好。問題是爲什麼第2塊和第3塊沒有。 –

相關問題