SqlServer中如何解決session阻塞問題

2022-09-21 16:09:13 字數 3084 閱讀 4600

簡介

對於資料庫運維人員來說建立session或者查詢時產生問題是常規情況,下面介紹一種很有效且不借助第三方工具的方式來解決類似問題。

最近開始接觸運維工作,所以自己總結一些方案便於不懂資料庫的同事解決一些不太緊要的資料庫問題。類似方法很多理論也很多,我就不做深究,就是簡單寫乙個方案,便於菜鳥使用的。

阻塞理解

在sql server 中當乙個資料庫會話中的事務正鎖定乙個或多個其他會話事務想要讀取或修改的資源時,會產生阻塞(blocking)。通常短時間的阻塞沒有問題,且是較忙的應用程式所需要的。然而,設計糟糕的應用程式會導致長時間的阻塞,這就不必要地鎖定了資源,而且阻塞了其他會話讀取和更新它們。

例子為了更好說明,下面用乙個例子來介紹。建立乙個表並插入資料,然後建立不同的session,同事阻塞session。具體的**截圖如下:

1.建立表employee

2.插入測試資料

現在我們有了測試表,表中有12條資料,開啟另乙個查詢對話方塊在ssms中(意味著重新建立了乙個session)

3.在新的查詢視窗中首先要開啟事務,然後寫乙個插入語句

在這個地方,我們能看到開啟了乙個事務。但是沒有end tran 來終止事務,因此事務狀態為「open」,現在執行指令碼來看一下當前看起的執行處於「open」狀態的session。

現在能夠看到如上圖展示一樣,執行的查詢正在open狀態的session。我們執行了這個命令但是沒有完結它,dba會聯絡這個session的建立者來完成事務,或者回滾事務。

現在讓我們建立另乙個session,更新一條記錄並且不提交,即讓查詢session的狀態為「open」。因此在新的查詢視窗中 寫乙個語句來執行如下:

這裡會看到系統正在執行後沒有完成語句的狀態(因為上乙個事務沒有關閉導致表鎖,這個不能插入),現在可以在另外的視窗查詢一下阻塞的情況,程式設計客棧如下檢查阻塞的session。

如上所示,阻塞的session id是58,由於我們更新查詢導致阻塞了54的執行,54就是我們插入資料未提交的批處理。

現在我們能搞清楚阻塞的原因,也就可以從容解決阻塞了。

解決方案1

在了解業務的情況下,可以直接使用kill session id的語句來終止某個阻塞的session。

方案2在執行的事務的起始加入「set lock_timeout 1000」 語句,這表示如果阻塞超過1000毫秒,這個請求將被終止。

方案3回滾或者提交事務。這個就不細說了。

下面是所有語句的**:

/****creating dummy table employee ****/

create table employee ( empid int not null, name nchar(10) null, city nchar(10) null ) on [primary] go

/**** insert dummy data in employee table *****/

insert into employee values(1245,'george','jax'), (1045,'peter','anadale'), (1157,'john','dallas'), (1175,'pete','topeka'), (875,'petron','vienna'),

(2311,'kohli','mumbai'), (1547,'peter','kansas'), (3514,'abian','khi'), (4251,'ghani','alexandria'), (957,'ahmed','vienna'), (1084,'bhanu','manderin'),

(2954,'ganeshan','mcclean')

/***** insert query in new session ****/

begin tran insert into employee values(1245,'george','jax')

/**** query to che currently running sessions ****/

select distinct name as database_name, session_id, host_name, login_time, login_name, reads, writes from sys.dm_exec_sessions

left outer join sys.dm_tran_locks on sys.dm_exec_sessions.session_id = sys.dm_tran_locks.request_session_id

inner join sys.databases on sys.dm_tran_locks.resource_database_id = sys.databases.database_id

where resource_type <> 'database' --and name ='specific db name'

order by name

/**** update query in new session ****/

update employee set name = 'sheraz' where empid = 1245

/**** qu程式設計客棧ery to check blocking queries with session id ****/

select session_id, blocking_session_id, text from sys.dm_exec_requests cross apply sys.dm_exec_sql_text(sql_handle);

/*** commandargdkagin if you want to kill blocking session ****/ kill (54)

總結自己也使用過多種不同的語句來查詢定位阻塞甚至死鎖,然後解決,這裡也是介紹一種臨時解決方式。萬變不離其宗,歸根結底還是因為**甚至資料庫設計上存在很多問題才導致的阻塞,比如缺失索引、事務中的查詢效能和邏輯順序存在問題、t-sql語句效能引起的等等不一而足。對於一些常年解決類似問題的dba人員來說沒啥價值,但是對於不太理解資料庫的人來說還是能暫時解決一些緊急問題,當然最後還是要把理論基礎打好才能盡可能的杜絕類似情況。

本文標題: sqlserver中如何解決session阻塞問題

本文位址: /shujuku/mssql/166209.html

SQL Server的「警報」問題應該如何解決

問 sql server的警報問題應該如何解決?檢查你是否使用了最新的sql server service pack。因為在最新的sql server service pack中已經修補了很多sql server使用警告 alerts 的漏洞。應該確保在你的系統中已經安裝了最新的sql server...

如何解決併發

雖然從巨集觀上,處理器是並行處理多項任務,但本質上乙個處理器在某個時間點只能處理乙個任務,屬於序列執行。在單處理器的情況下,併發問題源於多道程式設計系統的乙個基本特性 程序的相對執行速度不可 它取決於其他程序的活動 作業系統處理中斷的方式以及作業系統的排程策略。在分布式環境下,併發產生的可能性就更大...

git如何解衝突 如何解決Git中的合併衝突

我發現合併工具很少能幫助我理解衝突或解決方案。我通常更成功地在文字編輯器中檢視衝突標記並使用git log作為補充。提示一我發現的最好的事情是使用 diff3 合併衝突樣式 git config merge.conflictstyle diff3 這會產生如下衝突標記 the common ance...