2018年6月5日 星期二

WITH (NOLOCK) 實作與驗證

建了一個USER資料表,包含ID與金額欄位




撰寫一個簡單的TRANSACTION,更新ID=3的USER金額




Transaction有正常begin與commit,所以再次select時,資料正確。




再來我故意將commit拿掉,此時Transaction執行後將無法結束(也就是TABLE會被LOCK)
從參數 @@TRANCOUNT知道此TRAN已經執行了(一次),但因為沒有commit,資料都還沒真的寫入。




這時候在回頭執行SELECT時,會撈不出資料




但是!
如果此時加入 WITH (NOLOCK),就可以撈出來了!!
可以看到值也已經更改,因為UPDATE有執行到 (請記得資料還沒COMMIT)




這時候回頭加入rollback,再執行一次transaction,
資料會復原,TABLE也會解除LOCK




此時一般的SELECT就可以執行了,不會再TIMEOUT
而數值會恢復到執行前的狀態(因為資料rollback了)




所以如果某個系統程序執行了一段冗長耗時的TRANSACTION
所有相關的TABLE在執行期間都會LOCK,此時某人要撈資料就必須下WITH (NOLOCK)

以上例子:
  • 金額amount會在Transaction內異動,不適合搭配NOLOCK撈取。
  • ID或姓名name,可使用NOLOCK,避免Transaction執行間無法撈取。


附帶一提,如果剛好要撈的資料欄位必須等TRANSACTION結束(不能用NOLOCK),
又不想讓USER看到逾時的話,可以改用NOWAIT判斷,然後提示USER,如下:




關於 NOWAIT 的實作範例可 參考這裡