【发布时间】:2015-03-24 22:54:13
【问题描述】:
我有一组正在执行的工作进程 (System.Threading.Thread) MSSQL Server 上的查询。在某些情况下,(即长期修复的错误)查询需要很长时间才能执行,并且我被要求为管理员用户(此应用程序的,而不是数据库管理员)提供一种方法从应用程序中找到并终止该查询。
我在我的 DBMS 中找到了this post with a SQL query I can use to get a list of open SQL commands,但我似乎无法在结果集中找到任何唯一标识一个特定线程挂起的 SqlCommand/Transaction/Connection 的数据
背景信息:为了使用 Visual Studio 2013 和 SSMS 研究这种可能的解决方案,我创建了一个类(在 VS,.net 4.5 中),它包含一对线程,“worker”和“watcher”。 Worker 打开一个事务,并在其包装类上为其分配一个引用(因此我可以从“观察者”线程的角度在断点处进行一些探索)。然后,它运行一个“模拟长时间运行的查询”命令,一个 WAITFOR... 同时,Watcher 休眠,直到工作人员等待长时间运行的查询完成,然后命中一个断点。此时,我切换到 SSMS 并从上面的链接运行查询的修改版本:
SELECT * FROM sys.dm_exec_requests req CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext WHERE wait_type = 'WAITFOR'
然后我返回 VS 并深入研究本地变量(包括对“Worker”创建的 SqlTransaction、SqlConnection 和 SqlCommand 的实例本地引用),以尝试找到任何字段的值与SELECT 查询的结果集...
下面是运行这些查询的类类型示例。 (忽略任何关于连接/事务等的挑剔细节 - 请放心,我的连接已打开,所有基本的东西都在起作用)
public class WorkerThreadTest {
private SqlTransaction workerTransaction;
private SqlConnection workerConnection;
private SqlCommand workerCommand;
private System.Threading.Thread worker;
private System.Threading.Thread watcher;
WorkerThreadTest() {
worker = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
watcher = new System.Threading.Thread(new System.Threading.ThreadStart(Watch));
worker.Start();
watcher.Start();
}
private void Run() {
// Paraphrasing here //
workerTransaction = new Transaction(foo);
workerConnection = new SqlConnection(foo);
// Again, paraphrasing:
workerCommand = new SqlCommand("WAITFOR DELAY '0:05';", workerConnection, workerTransaction);
workerCommand.Execute(foo); // Thread will wait on this line for 5 minutes
bool placeBreakPointHere = true;
}
private void Watch() {
System.Threading.Thread.Sleep(foo); // Wait enough time for worker to execute its command
bool placeBreakPointHere = true;
// Here is where I explore my locals
}
}
// Inside main program:
WorkerThreadTest myWorkerThread = new WorkerThreadTest();
这是在工作线程执行 WAITFOR 后从 SQL 查询返回的示例行:
session_id request_id start_time status command sql_handle statement_start_offset statement_end_offset plan_handle database_id user_id connection_id blocking_session_id wait_type wait_time last_wait_type wait_resource open_transaction_count open_resultset_count transaction_id context_info percent_complete estimated_completion_time cpu_time total_elapsed_time scheduler_id task_address reads writes logical_reads text_size language date_format date_first quoted_identifier arithabort ansi_null_dflt_on ansi_defaults ansi_warnings ansi_padding ansi_nulls concat_null_yields_null transaction_isolation_level lock_timeout deadlock_priority row_count prev_error nest_level granted_query_memory executing_managed_code group_id query_hash query_plan_hash statement_sql_handle statement_context_id dbid objectid number encrypted text
112 2 2015-03-24 16:34:12.433 suspended WAITFOR 0x01004300C7A0DC2CB05D23780200000000000000000000000000000000000000000000000000000000000000 118 -1 0x06004300C7A0DC2CF07EA34A0400000001000000000000000000000000000000000000000000000000000000 67 1 9E1EF06D-A755-4EBD-82AA-B030F8B6D19B 0 WAITFOR 72294 WAITFOR 1 1 433172712 0x0000FFFFFFFFFFFFFFFF 0 0 0 72294 4 0x0000000243685468 0 0 0 -1 us_english mdy 7 1 0 1 0 1 1 1 1 2 -1 0 0 0 2 0 0 2 NULL NULL NULL NULL 67 NULL NULL 0 (@ContextInfo varbinary(10))SET CONTEXT_INFO @ContextInfo WAITFOR DELAY '0:05';
有什么方法可以唯一标识与我的工作线程的特定实例匹配的行?
(注意:不能保证主机名、ip 或查询文本是唯一的)
【问题讨论】:
-
另外,我不偏爱 dm_exec_requests,任何识别 session_id 的方法,或任何其他杀死查询 DBMS 端的方法都可以。
标签: c# .net sql-server multithreading