我正在开发一个多线程应用程序 (VB.Net/C#),它正在处理 SQL 服务器数据库。
通常,我的客户抱怨应用程序显示“死锁”-like 关于所谓的 SQLClient 的异常,并且通过重新启动应用程序,一切都再次正常运行(一段时间)。
根据描述,我不相信我的客户面临真正的死锁(一个线程在等待另一个线程),但我相信我正在处理两个数据库请求,很可能在同一个表上,一个事务需要那么多它阻止其他交易的时间,但这只是一个猜测,我想确定这一点。为此,我正在考虑询问数据库哪些线程当前正在访问哪些表,希望这能给我一些信息。
在此处的网站上搜索时,我发现了另一个问题dm_db_index_operational_stats
中提到的表格,但作为一个新手,这看起来很复杂,因此我想问一个简单的问题:
我如何知道哪个应用程序的哪些线程当前正在访问我的 SQL 服务器数据库中的哪些表?显然,信息(进程 ID、线程 ID、线程名称、调用堆栈的(上部)……)越多越好。
这存在吗?
就可能的解决方案而言:
我的应用程序基于此 DLL:
"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.dll"
...为了访问数据库执行以下操作(例如删除过时的条目):
Public Shared Sub ExecuteSQL(ByVal sSQL As String, ByVal ParamArray dbParams() As SqlParameter)
Dim oCommand As SqlCommand = Nothing
Try
oCommand = BuildCommand(sSQL, dbParams)
oCommand.CommandTimeout = 60
oCommand.ExecuteNonQuery()
Catch ex As Exception
Debug.WriteLine(ex.Message)
Throw
Finally
If oCommand IsNot Nothing Then ReleaseConnection(oCommand.Connection)
End Try
End Sub
我想添加一个锁定机制以避免此类问题,例如:
DatabaseConnection.Lock_Table("Table_which_is_handled");
ExecuteSQL(...); // working on "Table_which_is_handled"
DatabaseConnection.Release_Lock_Table("Table_which_is_handled");
这存在吗?
有人有想法吗?
提前致谢
与Dan Huzman讨论后编辑:Dan Huzman提到的
这个答案提到了以下 SQL 查询:
--Get xml_deadlock_report events from system_health session file target
WITH
--get trace folder path and append session name with wildcard (assumes base file name is same as session name)
all_trace_files AS (
SELECT path + '\system_health*.xel' AS FileNamePattern
FROM sys.dm_os_server_diagnostics_log_configurations
)
--get xml_deadlock_report events from all system_health trace files
, deadlock_reports AS (
SELECT CAST(event_data AS xml) AS deadlock_report_xml
FROM all_trace_files
CROSS APPLY sys.fn_xe_file_target_read_file ( FileNamePattern, NULL, NULL, NULL) AS trace_records
WHERE trace_records.object_name like 'xml_deadlock_report'
)
SELECT TOP 10
deadlock_report_xml.value('(/event/@timestamp)[1]', 'datetime2') AS UtcTimestamp
, deadlock_report_xml AS DeadlockReportXml
FROM deadlock_reports;
这是指位于客户计算机上的一些文件,很可能位于目录“C:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\Log”中(为了确定,请检查SELECT path FROM sys.dm_os_server_diagnostics_log_configurations
)。
我可以检索提到的“system_health*.xel”文件并将它们放在我的本地计算机上(假设在目录“C:\Temp_Folder”中),然后启动以下新查询:
--Get xml_deadlock_report events from system_health session file target
WITH
--get trace folder path and append session name with wildcard (assumes base file name is same as session name)
all_trace_files AS (
SELECT 'C:\Temp_Folder\system_health*.xel' AS FileNamePattern
FROM sys.dm_os_server_diagnostics_log_configurations
)
--get xml_deadlock_report events from all system_health trace files
, deadlock_reports AS (
SELECT CAST(event_data AS xml) AS deadlock_report_xml
FROM all_trace_files
CROSS APPLY sys.fn_xe_file_target_read_file ( FileNamePattern, NULL, NULL, NULL) AS trace_records
WHERE trace_records.object_name like 'xml_deadlock_report'
)
SELECT deadlock_report_xml.value('(/event/@timestamp)[1]', 'datetime2') AS UtcTimestamp
, deadlock_report_xml AS DeadlockReportXml
FROM deadlock_reports;
这是否会为我提供我正在寻找的信息,或者我是否需要在客户的计算机上打开 Microsoft SQL Server Management Studio 会话?
死锁不仅仅是一个线程等待另一个线程(阻塞),而是另外 2 个线程相互等待(死锁)。死锁通常可以通过查询/索引调整来解决,而不是去序列化数据库访问。
由扩展事件跟踪
xml_deadlock_report
捕获,system_health
将有助于识别最近死锁涉及的进程和资源。可以通过从评论中收集并添加到您的问题中的查询来获取死锁信息。