避免死結或將死結數目降至最低
在關聯式資料庫系統(RDBMS)中,死結是指無法進行兩個並行交易的情况,因為每個交易都在等待對方釋放鎖定。在本系列的第 1 部分中,我們知道了什麼是關聯式資料庫中的物件鎖定、不同類型的鎖定和死結。然後,在第 2 部分中,我們比較了封閉式鎖定與開放式鎖定的利弊。在本篇文章中,我們將探討造成死結的一些原因,以及避免死結或至少將死結數目降至最低的策略。
沒有效率的査詢
死結在某種程度上是不可避免的,但只要兩個交易的其中一個及時結束,死結就會很少發生並且不會導致災難。事實證明,封鎖問題最常見的來源之一是長而沒有效率的 SQL 陳述式,這些陳述式會導致資料庫在運行過程中「停止回應」。這可以通過兩個步驟進行補救:
- 最佳化效能較差的 SQL 陳述式,以便在盡可能在短時間內釋放鎖定。
- 識別在同一階段作業中執行任何長時間執行的 SQL 陳述式之前是否可以釋放鎖定。
例如,如果由於執行 DELETE 陳述式而取得鎖定,並且緊接著執行完整資料表掃描的 SELECT 陳述式,則應該確定是否可以在它們之間執行 COMMIT 陳述式。這將有助於更早地釋放鎖定。
嵌套交易
封鎖問題的另一個常見原因是休眠階段作業失去了對交易嵌套層級的追蹤。例如,如果應用程式取消 SQL 陳述式或逾時但沒有發出 COMMIT 或 ROLLBACK 陳述式,則資源可能會無限期地保持鎖定。處理此問題的一些方法包括:
- 在出現任何應用程式錯誤之後,請在應用程式的錯誤處理常式中提交 IF@@TRANCOUNT > 0 ROLLBACK TRAN 陳述式。
- 在任何啟動交易的預存程序中都要包含 SET XACT_ABORT ON 陳述式,特別是當它們在發生錯誤後沒有清理時。這樣,如果發生執行階段錯誤,任何開啟的交易都將被中止,並將控制權傳給用戶端。
- 如果連線共用由開啟連線並在將連線傳回至集區之前執行一些査詢的應用程式使用,則你可能需要考慮暫時停用連線共用。這樣,資料庫伺服器連線就會實際登出,導致伺服器回溯所有開啟的交易。
提取部分結果
死結的一個鮮為人知的來源是應用程式不能一次性提取所有結果列。這是一個問題,因為當査詢被傳送至伺服器時,應用程式必須能夠提取所有結果列以完成査詢。如果這種情況沒有發生,資料表會被鎖定,這會導致其他使用者被封鎖。因此,嘗試對應用程式進行編碼,以便它們提取所需的全部列,而不是將其分散在幾個反覆運算中。
總結
今天的文章列出了造成死結的幾個原因,以及避免死結和處理死結的策略。下週,我們將開始一個全新的話題。
Rob Gravelle 居住於加拿大渥太華,是一名有 20 多年經驗的 IT 專家。過住,Rob 曾為情報相關的組織(如加拿大邊境服務局和各種商業組織)建置系統。在業餘時間,Rob 是一名出色的吉他演奏家,並擁有多張 CD和數位發行。