之前遇到過這么一種情況:
連接數(shù)據(jù)庫的部分Session會出現(xiàn)不定時的阻塞,這種阻塞時長時短,有時候持續(xù)較長時間,有時間持續(xù)時間較短,沒有什么規(guī)律。
之后分析相關存儲過程和代碼寫法,發(fā)現(xiàn)是阻塞源頭的存儲過程中開啟了事務,而應用程序在調用存儲過程發(fā)生異常之后沒有進行特別的處理(提交或者回滾),
那么在執(zhí)行方法發(fā)生異常之后,連接關閉了,但是數(shù)據(jù)庫中遺留有活動事務(dbcc opentran對應的SessionId是sleeping狀態(tài)),于是就產生了阻塞。
關鍵是活動事務會不定時自己消失,就有點詭異了,這是本文的重點。
這種機制跟連接池有關:
當應用程序連接數(shù)據(jù)庫的時候開啟了連接池,如果應用程序調用了一個開啟了事務操作的存儲過程,
當發(fā)生異常的時候,有可能會出現(xiàn)數(shù)據(jù)庫連接關閉,而存儲過程中的事務既沒有提交,也沒有回滾的情況。
這種情況下就會產生“孤立事務”,也就是說,因為打開事務的數(shù)據(jù)量連接斷掉了,而事務還處于活動狀態(tài),
實際上開啟連接池的情況下,數(shù)據(jù)庫連接的關閉,并不是物理上的關閉,而是將數(shù)據(jù)庫連接返回到連接池。
此時如果沒有外界的干預,包括沒有對這個數(shù)據(jù)庫連接沒有被重用,或者這個連接沒有物理斷開,或者是沒有重啟應用程序,或者沒有數(shù)據(jù)庫服務器,這個事務將一直持續(xù)下去。
因為活動事務將阻塞其他Session對相關表的排他性訪問,所以就表現(xiàn)為阻塞。
如何判斷是否發(fā)生了連接池中的連接重用
首先,一個連接數(shù)據(jù)庫的過程中,有沒有重用連接池中的連接,在SQL Server中有哪些區(qū)別?
以ado.net為例,如果在連接字符串中加入pooling=false;則表示不啟用連接池.
如下,連續(xù)執(zhí)行兩次數(shù)據(jù)庫訪問,兩次數(shù)據(jù)庫訪問均在連接字符串中加入了pooling=false;表示不啟用連接池