Sql-Server

有效辨識阻塞查詢的框架

  • March 13, 2018

我需要一個常式來有效地辨識哪些查詢導致阻塞。這與我之前的問題有關如何找到仍然持有鎖的查詢?.

我知道網上有很多關於這方面的資料,但所有這些資料都是基於這樣一個前提,即活動會話上的最後一條 SQL 語句很可能是獲得鎖的那個(因此產生了阻塞),這並不總是真的(在我的情況下,從來沒有)。

我已將時間設置blocking-process-threshold為 30 秒並開始分析阻塞程序報告 (BPR)。

每次發生阻塞時,當達到門檻值時,就會觸發這些報告。

它包含有關阻塞 spid 和阻塞 spid 的資訊。

業務流程再造範例

通常,阻塞 spid 在獲取並持有資源(表、頁或行)鎖定的語句之後執行幾條語句:因此,儘管有報告內容,我仍然不知道究竟是哪個查詢導致了該塊。

通常 SQL Server DMV 只顯示每個 的最後一個 SQL 文本session_id,與活動鎖相關的 DMV(例如sys.dm_tran_locks)也沒有解決這個問題。

調整阻塞查詢不是最好的方法:我們的應用程序都基於嵌入在客戶端程式碼中的動態 SQL,我們不使用儲存過程,並且基於我到目前為止看到的阻塞,所有被阻塞的查詢都被正確索引並寫了。

我認為解決這個問題的一個選擇是收集候選查詢,這可能會產生阻塞,然後使用在 BPR 上收集的時間戳和 spid 查找此資訊。你同意?如果是這樣,您能否指出一種使用 xEvents 以盡可能少的成本來做到這一點的方法?

我建議使用 XEvents 會話尋找長時間執行的會話。

您描述的問題聽起來像是您的客戶端程式碼正在執行逐行處理(RBAR)處理,而不是使用有效的基於集合的方法。

設計不佳的客戶端應用程序可能會執行以下操作:

  1. 連接到 SQL Server 以獲取需要處理的項目列表。查詢結果保持打開狀態,直到處理完所有行。
  2. 對每一行執行一些長時間執行的過程。
  3. 關閉查詢。

應該發生的是:

  1. 連接到 SQL Server
  2. 執行查詢,在本地記憶體查詢結果,然後關閉連接。
  3. 在不保持原始查詢打開的情況下對每一行執行長時間執行的程序,從而防止阻塞。

可以使用快照隔離行版本控制來實現 SQL Server 的解決方法。有關詳細資訊,請參閱此 Technet 文件。從本質上講,行版本控制允許寫入者不阻塞讀取器,從而大大減少阻塞。

引用自:https://dba.stackexchange.com/questions/200099