SQL SERVER 查詢性能優化——分析事務與鎖(四)


上接SQL SERVER 查詢性能優化——分析事務與鎖(三)

 

二、死鎖的原因及相關處理

       死鎖的原因很多,尤其是前端應用程序沒有合理的使用事務,或者對錯誤處理不當而導致事務長期持有而沒有關閉。接下來講講最常見的幾種死鎖情況,並提供可能的解決方法。

1.費時的查詢事務

2.不正確的事務或事務隔離等級設置

3.事務未正確處理

4.未檢測到的分布式死鎖

5.鎖定數據粒度太高或太低

6.Compile Blocking

 

  (一)費時的查詢事務

       當查詢或事務所花的時間較長時,可由SQL SERVER 2005/2008 動態管理視圖sys.dm_exec_requests提供相關信息(也可觀察sysprocesses系統視圖),如status字段為“running”,wait_type為非“NULL”值。“running”代表該進程依然在執行,而wait_type則表示該進程是否在等待資源。如下圖。

 

       這也可以從SQL SERVER 2005的Microsoft SQL Server Management Studio管理工具中的活動監視器--》進程信息--》查看相關信息。如下圖,所圈出的相關字段可以觀察進程之間的相關信息。

 

 

 

      如上圖所示,進程“55”被“54”鎖住,也可以從“等待類型”列中看出相關信息。

     通過SQL PROFILER工具中觀察“T SQL”事件下的“SQL StmtCompleted/SQL BatchComplete”,或是“存儲過程”事件類別下的“SP StmtCompleted/SP BatchComplete/RPC Complete ”等事件,可觀察SQL語句執行情況,並通過TextData(呈現T-SQL語句執行內容)Duration(語句執行所需的時間)字段判斷哪一句語句是否執行時間過長而導致鎖定行為。如下圖1、圖2。

 

圖1

      如圖1中圈出來的地方,沒有結束時間,所以此SQL語句還在繼續等待。

 

圖2

     如圖2中圈出來的地方,雖然有執行結束時間,但是duration的執行時間過長,也就是說此SQL語句等待了這么長的時間,等待其他事務釋放資源。

 

     如果查詢語句使用大量系統資源導致查詢耗時過長,可能伴隨的現象有:處理器,硬盤I/O,內存等的使用率很高。SQL PROFILER工具中的“錯誤和警告”事件類別中的Missing Column Statistics,產生過多“存儲過程”事件類型的SP:Recompile事件也值得注意,前者表示無法產生有效的執行計划,后者表示存儲過程的編寫方式,無法提供高速緩存執行計划。“錯誤和警告”事件類別中的Hash warningSort warning則反映可能沒有好的索引可供使用。

 

建議解決方法

      如果事務執行時間過長,一直鎖住資源不放可能導致其他想要執行的事務被鎖。例如:設置事務隔離級別為“可重復讀取”,當查詢語句(SELECT)執行時間過長時,則更新語句(UPDATE)則無法對數據進行更新,最終導致系統癱瘓。出現此類情況,可以試着使用以下方式進行解決

1.新增或設置適當的索引以增加查詢速度

2.更新統計信息以避免執行計划使用舊的統計信息

3.重新設計數據表、存儲過程等對象

4.檢查是否過度使用觸發器和游標。

如果無法通過以上方式提高 工作效率,則可能要考慮修改系統的工作流程

1. 分割工作,不要同時執行所有的需求

2. 切割工作時間,將工作排至系統不繁忙的時段執行

3. 切割工作屬性,將工作交給另一個數據庫去執行,把查詢與更新分成兩個數據庫來執行。

 

 

(二)不正確的事務或事務隔離級別設置

      當死鎖是由於不正確的事務或事務隔離級別設置所導致時,SQL SERVER 2005/2008動態管理視圖sys.dm_exec_requests會提供相關信息,該SESSION_IDstatus字段值為“running”,wait_type非“NULL”值,通過sys.dm_exec_session動態視圖的transaction_isolation_level字段可以看出進程所設置的事務隔離級別。且從Microsoft SQL Server Management Studio管理工具中的“活動監視器--》進程信息”視圖,該進程的“打開的事務”字段顯示為非“0”值,表示為該進程仍握有事務資源。

       通過SQL PROFILER工具查找“TextData”,觀察前端傳遞命令中是否含有不當的事務設置,例如,設置隱含式事務(SET IMPLICIT_TRANSACTION ON)、事務隔離等級或是設置鎖定提示等。

 

建議解決方式:

       事務設置大多與實際業務邏輯有關,不容易界定是否有必要,如果你通過跟蹤文件找到不正確的事務或事略等級隔離設置時,也需要與開發者討論設置的必要性。尤其是當事務中包含大量數據的運算的情況,可能需要研究如何切割成較小的事務,但仍需要符合原來的數據完整性和業務邏輯要求。

 

 

(三)事務未正確處理

 

      開啟了事務,但是沒有回滾或沒有提交,形成了未提交事務。它的特征與觀察方式與上面所述相同。從下圖中可以看出進程“54”仍持有事務,但此進程停滯不做事,也無等待任何資源,但仍持有事務,從SQL SERVER 2005的Microsoft SQL Server Management Studio管理工具中的“活動監視器--》進程信息”視圖,進一步觀察“上一批”字段,檢查進程是否已經持有資源一段時間。

 

 

在SQL 2005(2008)執行代碼示例一,得到如下圖。

 

select spid 進程,STATUS 狀態, 登錄帳號=SUBSTRING(SUSER_SNAME(sid),1,30)

,用戶機器名稱=SUBSTRING(hostname,1,12)

,是否被鎖住=convert(char(3),blocked)

,數據庫名稱=SUBSTRING(db_name(dbid),1,20),cmd 命令,waittype as 等待類型

,last_batch 最后批處理時間,open_tran 未提交事務的數量

from master.sys.sysprocesses

--列出鎖住別人(在別的進程中blocked字段中出現的值)但自己未被鎖住(blocked=0)

Where spid in (select blocked from master.sys.sysprocesses) and blocked=0

 

 

 

 

建議解決方式

      利用SQL PROFILER 工具中的事務事件類別,錄制SQL SERVER所觸發的事務事件,也可以通過dbcc opentran (‘<數據庫>’)命令觀察針對某個數據庫執行最久的事務事件,由哪個程序擁有,如果沒有指定數據庫名稱或ID,則返回當前連接所在的數據庫執行最久的事務事件,一般未提交事務可能是由於未做好錯誤處理所造成的。

 執行dbcc opentran命令的之后,如下圖。其中UID是無意義的。

 

 

     例如,執行命令逾時,放棄批處理但未回滾事務。其中的錯誤處理,應該如下例一般。

If @@trancount>0

   Rollback tran

 

---或是設置:

 

Set XACT_ABORT on

 

(上述設置是指當SQL SERVER 在發生任何錯誤時,都要回滾事務)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM