【问题标题】:How can I track calling code in a SQL Server trace?如何跟踪 SQL Server 跟踪中的调用代码?
【发布时间】:2011-08-03 13:32:05
【问题描述】:

我想使用 SQL Server 跟踪来跟踪有关哪些代码正在使用数据库的更多上下文。我打算在连接字符串上使用“应用程序名称”属性。如下所示:

object CallingObject; //set elsewhere
SqlConnectionStringBuilder connectionString = GetConnectionString();
connectionString.ApplicationName = CallingObject.GetType().ToString();
using (SqlConnection connection = new SqlConnection(connectionString.ToString()))
{
    // do your thing
}

除非产生的连接字符串种类繁多,这意味着 .net 的连接池不再有效。

如何在 SQL 跟踪中跟踪调用代码而不失去连接池的好处?

【问题讨论】:

  • 我有一个可能可行的想法,但是:您希望在跟踪中实现哪些关键目标? (这将告诉我这个想法是否成立)
  • 嗨,Marc,我想收集跟踪并使用该信息将 x% 的数据库活动归因于此代码,将 y% 的数据库活动归因于该代码。 (活动是 CPU、读取、写入、持续时间等...)
  • 嗯;好的-然后进行一些数据挖掘。我不认为这是直接“命中”,但对于 code-path 分析(例如,基于每个请求)我们使用mvc-mini-profiler,这对于查找时间位置很有用在单个请求中(比如说)被花费。在你的情况下不太有用,也许/
  • FWIW,感谢您对此的关注。
  • 我自己还没有测试过这个,所以我没有提交作为答案,但是不能在命令前加上评论吗? IE。类似于:string.Format("/*{0}*/\n{1}",CallingObject.GetType().ToString(),myCommand);

标签: .net sql-server ado.net


【解决方案1】:

只要您使用 SQL Server,并且只要您拥有(或可以拥有)集中式连接创建逻辑,您就可以使用 CONTEXT_INFO 功能:http://msdn.microsoft.com/en-us/library/ms187768.aspx

我们这样做是为了跟踪多用户服务器端应用程序中的数据库连接。每次创建新的数据库连接时(实际上是从连接池中重用,但在 ADODB/ADO.Net 代码中“创建”):

DECLARE @ContextInfoBinary binary(128); 
SET @ContextInfoBinary = Convert(Binary(128), 'XX' + Replicate(Char(0), 36) + 'Up to 90 characters of connection info - username, page, action, etc') 
SET CONTEXT_INFO @ContextInfoBinary

稍后,当您想“跟踪”连接时,可以将指定范围的上下文信息转换回 VarChar 内容:

SELECT RTRIM(hostname) AS hostname
    , hostprocess
    , RTRIM(program_name) AS program_name
    , CASE 
        WHEN SubString(Context_Info, 1, 2) = 0x5858
            THEN Replace(Convert(VarChar(90), SubString(Context_Info, 39, 90)), CHAR(0), '')
        ELSE 'UNKNOWN' 
        END AS ExtendedConnectionDescription
    --More stuff here, depending on what you're looking for
FROM master.sys.sysprocesses 

一些注意事项:

  • 由于应用程序名称功能存在连接池问题,我们专门采用了这个概念。能够在任何给定时间点跟踪特定用户和进程的阻塞原因对我们来说很重要。
  • 这会为创建的每个连接添加一个要执行的 DB 命令 - 这可能会或可能不会代表显着的开销,具体取决于您的应用程序设计
  • 此示例使用 VarChar(最多 90 个字符);如果您需要跟踪 NVarChar(扩展字符)数据,您的空间将减少到 45 个字符
  • 在本例中,我们保留了 36 个字节,这些字节可用于其他目的,例如防止触发器对某些连接执行。
  • 您可以使用sp_trace_generateevent 将值显式输出到跟踪,如以下相关问题所述:How do you access the Context_Info() variable in SQL2005 Profiler?

更新:

只有在重新阅读您的问题后,我才意识到您似乎只是明确地希望将信息添加到 Traces,而不是对您当前的连接进行临时分析(这更多是我将“应用程序名称”,抱歉);我专门看到的唯一有用的方法是sp_trace_generateevent 调用。如果您要这样做,我建议您也添加 connection_info,因为它不会再花费您(您已经拥有sp_trace_generateevent 的数据库往返)并且肯定会在以后帮助您进行其他类型的分析。

【讨论】:

  • 此过程还存在安全后果,您可能希望或不希望提供任意应用程序。另一个需要考虑的因素。
  • 这样就行了!谢谢陶。有一些后处理可以将自定义事件 (UserConfigurable:1) 与同一进程的统计信息相匹配。但我可以做到。
【解决方案2】:

【讨论】:

  • 我想从该数据库服务器端收集信息。虽然这些是客户端跟踪。
【解决方案3】:

为什么没有到数据库表的跟踪输出(最好在与运行跟踪不同的机器/实例上)?这样您就可以根据您的参数查询跟踪表,查看哪些操作占用了所有 CPU 百分比,查看它的命令文本等。

【讨论】:

  • 嗯,这就是我打算做的。除了这没有解决找出应用程序中的哪一段代码正在调用/调用每个查询/sproc的棘手部分
  • 首先,您应该尽量减少从代码中构建和调用的即席查询的数量。您的数据访问层应该让我在 95% 的时间里进行存储过程调用。在跟踪中,您将能够看到正在运行的存储过程或查询。但是你想看看是哪一段代码在调用它???考虑到跟踪的命令文本,我相信您能够非常快速地了解这一点。
  • 嗨冲浪者,感谢您花时间回答这个问题。跟踪的命令文本将告诉我正在运行的 sql,而不是正在进行调用的 C# 类或程序集。 (有关我试图捕获的信息类型,请参阅问题中的代码示例)。
  • 我想我没有在问题中说清楚。我应该补充一点,我们有几个产品 --> 几个数据访问层,它们调用重叠的存储过程......这就是我想要解决的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
相关资源
最近更新 更多