上午看到服務器上sql server佔的內存都超過90%,於是乎又手動重啓了sql服務,內存佔比是下降了,但是問題來了,這下好了,如何解決?
先是一陣kill,刪了一個進程又有新的進程出來?
網上有幾種解決辦法。一一試過了,感覺沒效果,還好,暫時這個死鎖還不影響其他服務的運行,不過得想辦法解決。
首先需要了解死鎖是如何產生的?
資源競爭,在兩個或多個任務中,如果每個任務鎖定了其他任務試圖鎖定的資源,此時會造成這些任務的永久阻塞,從而出現死鎖。打個比方,廚房裏有兩個廚師,然後只有一把菜刀,有一次,A廚師在用菜刀,B廚師也要用,那B廚師就只能等A廚師用完,再使用菜刀。
形成死鎖有四個必要條件:
請求與保持條件:獲取資源的進程可以同時申請新的資源;
非剝奪條件:已經分配的資源不能從該進程中剝奪。(A廚師在切菜,然後就要炒了,外面客人在催菜,所以剝奪不了。)
循環等待條件:多個進程構成環路,並且其中每個進程都在等待相鄰進程;
互斥條件:資源只能被一個進程使用。
其次如何解決死鎖問題?
1、清除死鎖
2、使用無鎖查詢
看了下書,書上淡淡的甩了一句:一般是撤掉一個最不重要的事務,釋放它持有的資源,讓重要的事務先運行,之後再處理這個事務。當然事先避開死鎖的發生是解決死鎖問題的最好方法。(這說得也沒毛病,只不過實操性比較差,只是理論上講。)
總結其中的處理步驟如下:
1、首先找到這個死鎖對應的信息;
在這裏可以看到blkby就是導致死鎖的進程,然後command代表的是引起死鎖的操作。那如何查看這個進程裏具體是那個語句操作導致的呢?使用dbcc inputbuffer(spid)來查看。這裏其中的evnetinfo就是導致死鎖的操作語句。
2、然後需要確定你的程序裏面哪裏執行了這些語句,然後是否存在sp_who2查詢出來的,引起死鎖的command,比如,command是delete,那在程序中查找相關操作。如果在不影響業務的情況下,可以刪掉這部分操作,或用其他方法代替?或改成定時任務等,優化這部分操作再試試。
就像上圖,根據提示的信息,找到對應的delete語句,然後看了下這個語句對主要的業務不影響,所以索性去掉,果然解決了。
其中有幾個疑問:
1、程序運行過程中出現死鎖是否正常?如果出現少量死鎖,過一段時間,死鎖是否會自動解除?(大神說會自動解除)
2、重啓sql server服務是否能解除死鎖?重啓服務器呢?
3、如何在程序開發中避免這種問題?sql語句如何設計才能預防這種問題?
4、此程序一直運行2-3年,都從未出現死鎖問題,爲何重啓sql server服務後就會出現,而且還是比較頑固的存在。
這裏面我也用了sql 的profiler,可以看到相關的死鎖分析,但是感覺還沒掌握住這個工具。
寫得有點亂,一步一步整理吧。如遇到類似問題的,可以互相交流下。
其中參考學習了以下鏈接:https://www.cnblogs.com/yanggb/p/10944350.html