2009-08-26 152 views
4

我們有一位客戶遇到了我們的數據庫應用程序出現的一些阻塞問題。我們讓他們運行阻塞進程報告跟蹤,他們給我們的跟蹤顯示阻塞發生在SELECT和UPDATE操作之間。跟蹤文件顯示如下:默認SQL Server隔離級別更改

  • 相同的SELECT查詢正在不同的隔離級別執行。一條曲線顯示一個Serializable IsolationLevel,而後面的曲線顯示一個RepeatableRead IsolationLevel。執行查詢時我們不使用顯式事務。
  • 正在使用RepeatableRead隔離級別執行UPDATE查詢,但被SELECT查詢阻止。這是預期的,因爲我們的更新包含在一個明確的事務中,並且帶有IsolationLevel的RepeatableRead。

所以基本上我們是虧本,爲什麼SELECT查詢的隔離級別不會是默認的READCOMMITTED的IsolationLevel但是,更令人困惑的是,爲什麼查詢的IsolationLevel會隨時間而改變?只有一位客戶看到這種行爲,所以我們懷疑它可能是數據庫配置問題。

任何想法?

由於提前,

格雷厄姆

回答

6

在你的情況,我建議明確設置隔離級別快照 - 這將阻止通過防止鎖獲得在寫入(插入和更新)的方式讀,但那些讀取仍然是「好」的讀取(即不是髒數據 - 它不是一樣的NOLOCK)

通常我發現,我有我的查詢鎖定問題,我手動控制應用的鎖。例如我會使用行級鎖執行更新以避免頁/表級鎖定,並將我的讀取設置爲readpast(接受我可能會錯過某些數據,在某些情況下可能會好) 鏈接|編輯|刪除|標記

EDIT--綜合所有的評論到答案

作爲優化過程的一部分,SQL服務器避免越來越COMMITED讀取它知道沒有改變一個頁面上,並自動回落到較低的鎖定策略。在你的情況下,sql server從可串行讀取下降到可重複讀取。

問:感謝有關降低隔離級別的有用信息。你能想到它首先會使用Serializable IsolationLevel的任何理由,因爲我們不使用SELECT的顯式事務 - 我們知道隱式事務將使用ReadCommitted?

答:默認情況下,SQL Server將使用Read Commmited(如果這是您的默認隔離級別),但如果您沒有在查詢中額外指定鎖定策略,則基本上是對sql服務器說:「做你認爲最好的,但我的首選是Read Commited「。由於SQL Server可以自由選擇,因此它可以優化查詢。 (sql server中的優化算法非常複雜,我自己也不完全理解它)。在事務中不顯式執行不會影響sql server使用的隔離級別。

問:最後一件事,SQL Server是否會增加隔離級別(可能需要鎖的數量)以優化查詢似乎是合理的?我也想知道,如果它繼承了上次使用的隔離級別,重用連接池是否會影響這一點?

答:Sql服務器將會這樣做,稱爲「鎖定升級」的過程的一部分。從http://support.microsoft.com/kb/323630,我引用:「Microsoft SQL Server動態地決定何時執行鎖定升級。當做出這個決定時,SQL Server會考慮在特定掃描中保留的鎖的數量,整個鎖的數量事務,以及整個系統中用於鎖定的內存。通常,SQL Server的默認行爲會導致鎖定升級,這些鎖定升級僅發生在可以提高性能的那些點上,或者必須將過多的系統鎖內存減少到更多但是,某些應用程序或查詢設計可能會在不需要的時候觸發鎖升級,並且升級的表鎖可能會阻止其他用戶「。

儘管鎖升級與改變隔離級別並不完全相同,但是查詢運行得很好,這讓我感到驚訝,因爲我不希望sql server比默認隔離級別允許的更多的鎖。

+0

沒問題灰。感謝有關降低隔離級別的有用信息。你能想到它首先會使用Serializable IsolationLevel的任何理由,因爲我們不使用SELECT的顯式事務 - 我們知道隱式事務將使用ReadCommitted? – Graham 2009-08-27 07:38:03

+0

謝謝阿什。如果您將您的評論與答案結合起來,我會將其標記爲答案併爲您投票。 – Graham 2009-08-27 13:34:40

+0

最後一件事,SQL Server是否會增加隔離級別(並且可能是所需的鎖的數量)來優化查詢似乎是合理的?我也想知道,如果它繼承了上次使用的隔離級別,重用連接池是否會影響這一點? – Graham 2009-08-27 13:48:22

3

有關SQL爲什麼會通過逐步升級需要更多鎖的更多信息:這是不正確的,升級會減少(而不是增加)所需鎖的數量。表鎖是一個單一的鎖,而所有的頁鎖或行鎖都需要從較低的級別進行。鎖定升級始終是由於一個原因:取得更高級別鎖定比鎖定所有更低級別對象更有效

例如,可能沒有可用的索引來有效鎖定。即如果您在字段中的2010年所有記錄上使用UPDLOCK進行計數,並且該日期字段中沒有索引,則這將需要2010年每條記錄上的行鎖定,如果記錄中有多條記錄,則該鎖定效率不高,並且頁面鎖定也無濟於事,因爲它們大概是在頁面中隨機分佈的,所以SQL需要一個表鎖。此外,SQL還必須鎖定其他記錄,以便在UPDLOCK保持不變的情況下更改爲2010年,並且此字段上沒有索引來執行範圍鎖定,SQL沒有選擇,只能採取表鎖來防止發生這種情況。最後一點是那些經常被優化的人忽略的一點:認識到SQL還必須「保護」已經在事務中執行的查詢的完整性。

相關問題