Dirty Read (以下簡稱DR)在MS SQL 的Help 裡解釋如下:
"第二筆交易選擇的資料列已經被其他交易更新時,會發生未確認依存性 (Uncommitted Dependency)。此時,第二筆交易讀取的是尚未認可且可能被更新資料列的交易變更之資料。

例如,有一位編輯人員正在修改一份電子文件。進行變更時,第二位編輯人員複製了包含目前所有變更的文件,並將文件散發給預期的讀者。此時,第一位編輯人員認為截至目前的變更均有誤,所以移除了原先的變更後儲存文件。散發的文件包含不存在的修改,但這些修改不應該存在。如果能在第一位編輯人員決定不再進行變更後才允許其他人員讀取修改過的文件,即可避免這個問題。"

坦白說, 我一向看不太懂這些詏口的翻譯文, 不過大致可以推斷出, 當 DR 發生時, 表示我們的select 的資料, "可能"是錯的.

想對MS SQL 的鎖定機制有進一步認識的人, 可以參考這一篇

為了避免這種錯誤發生, 我們只有運用lock 的機制去避免, 但這往往必須用系統效能的降低來交換, 只不過, 在一個設計良好的系統中, 這種兩難可以達成一個平衡(trade-off balance).

但如果是發生在一個已經每天都滿載甚至超載(overload)的MS SQL 資料庫上呢? 我們會發現, 由於大量的Lock, 將會導致系統始終遊走於崩潰邊緣!

我在 sql-server-performance.com 這個網站上翻閱了一些文章, 其中這篇寫得不錯; 作者針對上述問題(row lock/page lock/table lock/...), 提供了兩點方案:
1) turn option "NOLOCK" on while SELECT
2) turn option "ROWLOCK" on while UPDATE and DELETE


關於"NOLOCK"及"ROWLOCK", 在此不再詳述, MSDN 裡都翻得到.

由於這種方法可能會造成DR, 筆者也特別說明, 進行重要的交易(如會計結帳), 不可用此方案.

以一個 ERP 而言, 絕大多數(往往超過50%)的查詢或報表, 並不一定需要"最及時"(updated)的資料; 如果我要查目前的庫存量, 那麼30秒前的庫存, 和目前的庫存, 即使有所差異, 那差異量和整月的交易量比起來也是微乎其微; 諸如此類的select statement, 其實是可以忽略 DR 的風險! 如果我們對這些 sql statement 加上 "NOLOCK"及"ROWLOCK", 可以使 DB 的效能超死回生, 那麼何妨一試!?

曾與人爭論"資料正確性"與"效能", 孰重孰輕!? 理論上, 提供100% 的資料正確性是MIS 的天職, 但實務上若遇到設計不佳的 DB 存取方法, 常造成使用者操作時要忍受無窮無盡的等待, 三不五時的"作業逾時",換算成全公司浪費的人力, 絕對比DR 的成本更加驚人 (何況前者是"一定會有"的顯性成本, 後者只是潛在成本),遑論使用者對系統的抗拒感造成日後的怒氣爆發! MIS 宜從多個角度思考何者為佳(對公司最好), 而非固執地抱著理論不放.

arrow
arrow
    全站熱搜

    cbw0731 發表在 痞客邦 留言(0) 人氣()