處理SQL DeadLock
今天是我的到職第一年。(晚點再發感慨文)
手上維護的案子,其實平常資料流量頗大,而且也有部分使用了SQL Truncation機制。
系統已經有一個老問題(此系統已經運行七八年之久),可是卻一直沒有很正式的處理&排除。
那就是在資料處理時,時常會有DeadLock的情形發生。
今天終於下定決心來處理。
平常,基本上的Select語法已經有套用With(NoLock)結避免。
PS:使用With(NoLock)是有風險的。可能造成資料不一致。
原因是,加了With(NoLock)會將忽略鎖定後的資料。
可能造成,資料不一致。請參考:RiCo技術農場
回到本文,其實處理DeadLock在我的想法中很困難。
主管給了我一條明路。
請參考:黑暗執行緒(愛逛的BLOG之一啊!!)
整體操作流程就跟黑大文章記載的一樣。
補充一點:SQL2008有內建的範本請見圖。(選擇TSQL_Locks)
或這是使用空白的範本,自行定義事件選取範圍。
我這次因為機器上為SQL2005,所以,基本上我選取的事件範圍跟黑大設定的一樣。
之後就開始執行。
執行過程,可以很清楚的看見所有執行過的Query(用過Profiler的人會跟我說這是廢話)。
今天在很有耐心的終於等到DeadLock出現(平常看到這個都很無奈,第一次看到他好快樂)。
結果也跟黑大的文章擷取的畫面一致。
找到EventClass=Deadlock graph點到那一個資料列下方會很清楚的出現衝突的SPID&指令,還有被犧牲的SPID。
不過,感覺指令並沒有顯示完全。
沒有意外,DeadLock是發生在我原本預計的SQL指令中。
這段指令是用一個Trancation包起來。
當中,流程大約是:
- Update TableA
- Update TableA
- Update TableB
- Update TableC set XXX=@XXX where ID=@ID
- Delete TableC Where 某區間
兩個衝突的指令是一樣的,只是Where 條件不同。
該錯誤顯示出是TableC 的主鍵被鎖定。
菜菜的推論是Delete誤了事。
由於,該Delete其實不用每次做這件資料處理就執行一次。
目前解決方式:
1.將上述指令5另外做一個Store Procedure並且設定排程執行。
2.將上述指令5移除每次執行的動作。
再來就是持續觀察啦!
希望菜菜的我想的沒錯。
以上文章若有任何錯誤或指教歡迎留言糾正!!
必定欣然學習求教。