切換到 RCSI
我工作的公司目前為我們開發的產品使用 SQL Server 數據庫(通常是最新的企業版)。
我會將它描述為一個 OLTP 數據庫,它在某種程度上同樣具有寫入和讀取密集型,並帶有許多時間關鍵型應用程序。除此之外,許多報告和圖形數據顯示在同一個 OLTP 數據庫(單獨的問題)中的資訊中,並針對許多以頻繁速率讀取和寫入的相同表。
我們通常會遇到阻塞發生的問題,它通常最終會減慢時間關鍵型應用程序的速度,甚至由於這些應用程序中的死鎖而導致問題。這個問題的常見解決方案似乎通常是對
nolock
有問題的查詢進行提示。老實說,我討厭這個解決方案,很長一段時間以來我都覺得這是嘗試解決這個問題的錯誤方法,從我讀過的所有內容中,我得出了相同的結論。一段時間以來,我一直試圖說服我的團隊相信 RCSI 是我們絕對可以從中受益的東西,尤其是考慮到我們的數據庫類型。他們似乎認為這是一個很大的風險,並且經常因為風險因素而推遲它,但我們繼續遇到性能問題,我們只是
nolock
對其進行提示。
- 我如何幫助證明我們的數據庫可以從使用 RCSI 中受益匪淺?
- 是否可以基於我們在測試環境中轉換為 RCSI 的實際生產數據庫執行性能測試?
我正在尋找一種向我們的團隊展示具體指標的好方法,以最終說服他們我們應該採用這種方法。
我相信你知道,僅僅因為很多人使用
NOLOCK
它並不意味著它是一個好主意——畢竟,如果你回溯得足夠遠,很多人會想到奴隸制、殺蟲劑、石棉、含鉛油漆和汽油等.都是好主意,也是。
NOLOCK
具有性能優勢,但不是因為它不使用鎖——這僅僅是因為它允許讀取器忽略其他讀取器或寫入器佔用的鎖。根據誰在對基礎表執行什麼操作,仍然可以阻止查詢NOLOCK
- 至少,Sch-S
仍然需要鎖。但是缺點很多,並且通常在它們發生之前被忽略 - 人們非常高興他們的查詢“快速” - 即使它們產生不正確或不一致的數據,特別是如果他們沒有註意到。使用
NOLOCK
/READ UNCOMMITTED
,您可以:
兩次讀取同一行(您已讀取的行在分配順序掃描之前移動)
完全跳過一行(您尚未閱讀的行移到掃描後面)
讀取可能永遠不存在的未送出行
由於掃描期間移動過多而出錯
在不同的狀態下連續讀取不同的列
- 甚至在半送出狀態下細化單個值(來自 Paul White 的優秀範例。)
該怎麼辦
您可以避免這些風險。預設隔離級別 (
READ COMMITTED
) 當然也不是沒有數據一致性風險,只是NOLOCK
增加了很多風險。我看到“快照”被拋出了很多 - 雖然它們聽起來很相似,但讀取送出的快照隔離與快照隔離完全不同。Kendra Little在這裡有一篇詳盡的文章,值得一讀。
有人說“沒有人因為使用快照隔離而被解僱”。我實際上可以想像這件事很有可能的場景。快照隔離具有明顯不同的語義,需要正確實施程式碼更改。更多變化=更多風險。
Read Committed Snapshot Isolation 可以在幾乎沒有程式碼更改的情況下實現,並且通常是人們建議您從
NOLOCK
/切換時的意思READ UNCOMMITTED
。然而,由於簡單地在數據庫級別啟用 RCSI,也有可能引入行為更改(請參閱Kendra 文章中的第 3 項以獲取範例)。雖然我個人認為 RCSI 比 好得多
NOLOCK
,但您需要記住,不能保證性能會更好。RCSI 通過在 tempdb 中創建行的版本來工作,以便任何給定的會話在需要時都有自己的行副本。如果 tempdb 是您系統上的瓶頸,這可能不會那麼順利。此外,在數據庫級別啟用已送出讀快照意味著所有數據更改將在每行增加 14 個字節。這意味著,為了證明切換是值得的,如果 tempdb 目前不是最佳的,您應該充分裝備 tempdb 以支持額外的負載,並且您需要為現有表準備好需要更多磁碟空間,並且,最終,在記憶中。如果 tempdb 已經飽和,或者您已經接近磁碟容量,或者記憶體已經耗盡,則 RCSI 可能無濟於事。
(當然,通常還有其他方法可以提高性能,如果
NOLOCK
不值得冒險,並且您沒有 RCSI 的成本。例如,當您有很多 CPU 成本。列儲存索引對於特定的工作負載很有用。顯然,細粒度的索引和查詢調整可能是有益的。)對於手頭的問題:
我建議您專注於確保您的查詢返回正確的結果,而不會對性能造成明顯影響 -*與預設隔離級別相比。*比較
NOLOCK
並不公平,除非您對上述所有風險完全滿意。Kendra 的文章詳細介紹了衡量影響的一些細節,但基本上您希望在相同的工作負載和相同的外部壓力和並發性的情況下進行前後測量:
- 這些查詢的查詢時間為
NOLOCK
今天 (sys.dm_exec_query_stats
)- 整體性能指標 - 等待、I/O 延遲、tempdb 使用情況、記憶體使用情況,甚至頁面預期壽命
您可以使用目前用於衡量性能的任何方法來執行此操作 - 如果您沒有方法,我可能會建議監控工具可能是值得的,即使只是試用。(免責聲明:我曾經為一個工作過。)
沒有什麼神奇的“告訴我我的工作量是否比不使用 RCSI 更好”——這將取決於性能的哪些方面對你很重要,哪些已經接近瓶頸,哪些將證明——在你的具體情況下- 總體收益或損失(再次假設其他一切都保持不變)。
並且您可能會通過定性論據而不是(或除此之外)僅僅是“指標”來說服他們。
進一步閱讀(上面重複了一些連結):
在我目前的工作中,大多數數據庫對象使用 (NO LOCK) 或 READ UNCOMMITTED 隔離。我同意這是一個糟糕的解決方案,但如果你回溯到足夠遠,它會經常使用。
我對首字母縮寫詞 RCSI 並不熟悉,但在Google搜尋時我發現它指的是使用 Read Committed Snapshot Isolation。是的,如果您遇到鎖定和死鎖問題,您應該使用 SNAPSHOT ISOLATION。
我認為證明這一點的最佳方法是創建生產系統的兩個虛擬化複製,在其中一個上使用快照隔離,在每個上模擬典型的使用模式,並驗證它是否提高了性能。
或者只是在較低的環境中執行它,然後一旦您驗證它是穩定的,就將更改遷移到生產環境。沒有人因為使用快照隔離而被解僱。