标记用于跟踪和调试的 sql 语句

Posted

技术标签:

【中文标题】标记用于跟踪和调试的 sql 语句【英文标题】:Tagging sql statements for tracing and debugging 【发布时间】:2008-12-22 15:42:30 【问题描述】:

我们有一家大型企业,由许多由 Oracle 10G 支持的新旧应用组成。当阻塞会话或死锁发生并且我们得到跟踪报告时,能够在 sql 中嵌入一些详细信息将非常方便,这样我们就可以知道是什么应用程序,特别是它是从哪里执行的。除了帮助加快解决时间之外,它还可以帮助我们找到业务流程相互交叉的地方。我们对如何实现这一点有一些想法,但我很好奇这是否已经是一个已解决的问题。任何成功(或其他)尝试的想法或细节将不胜感激。

【问题讨论】:

【参考方案1】:

您可以标记正在通过 Oracle DBMS_APPLICATION_INFO 包执行的 SQL 块。这适用于任何应用程序语言,适用于数据库引擎本身,并且不会将您的 SQL 语句与 cmets 混淆(无论如何,智能 cmets 都是邪恶的)。更重要的是,Oracle 的各种工具可以识别数据并帮助您在故障排除或调整时使用它。

【讨论】:

无论如何,鼓励 DUMB cmets。 “聪明的 cmets 是邪恶的”?嗯?! “smart cmets are evil Anyway”是对许多讨论的总结和参考,例如c2.com/cgi/wiki?CommentsAreCode。【参考方案2】:

我们动态地修改我们的 SQL 语句,以便执行它们的命令位于查询开头的注释中。这是有效的,因为我们进行自己的事务管理并拥有严格的框架。但基本代码很简单(在 Java 中......不确定其他语言将如何处理):

String sql = "SELECT * FROM USERS WHERE ID = ?";
Connection con = getConnection();
PreparedStatement ps = con.prepareStatement(getComment() + sql);
// etc

String getComment() 
  return " /* " + getCommandName() + " */ ";

JDBC 驱动程序完整地传递注释,并在 DBA 检查查询时显示在数据库中。为此,我们的命令架构维护了一个线程本地的命令名称堆栈。此外,我们的连接工厂使用我们自己的连接对象包装 JDBC 连接,这样即使人们针对裸机 Connection 实例进行编程,也存在此代码,而不是使用我们通常使用的友好帮助方法。

【讨论】:

【参考方案3】:
Properties jdbcProperties = new Properties();

this.jdbcProperties.put("user", userName);
this.jdbcProperties.put("password", password);
this.jdbcProperties.put("v$session.program", "YourApplicationName");
DriverManager.getConnection(url, jdbcProperties);

然后通过针对您的连接的程序列分组来检查 v$session,很简单..

【讨论】:

【参考方案4】:

“我们都知道什么应用程序,并且 特别是在哪里执行 从” 您没有提及您的应用程序是用什么编写的。当从 PLSQL 程序发出 SQL 时,11g 会获取其他信息,您可能需要记住这些信息,具体取决于您的环境、潜在的数据库升级时间范围和代码更改所涉及的工作量. 如果从多个应用程序发出相同的 SQL,它将(大部分)在 v$sql 中只有一个条目,因此您可能无法将其追溯到一个应用程序。

【讨论】:

【参考方案5】:

我想在 sql 语句中嵌入 cmets,以便它们在 tkprof (10.2.0.4) 中一直被标记。似乎在某些时候删除了斜线星号或双连字符 cmets。然后我使用了一个假的 sql 提示的语法,它确实通过 tkprof 持续存在,例如

/*+ testrun=4A */  

数据库忽略它,它满足我的需求。

【讨论】:

以上是关于标记用于跟踪和调试的 sql 语句的主要内容,如果未能解决你的问题,请参考以下文章

调试/跟踪嵌入式 sql

DBA应该知道的一些SQL Server跟踪标记

sql查询语句如何能让cpu一下跑满

oracle怎样开启sql跟踪

SQL 跟踪问题? 在 SQL 跟踪中,如何判断SQL语句执行是不是错误。

IDA调试跟踪