如何有效地跟踪Bug记录带有详细参数值的SQL

67次阅读
没有评论

共计 6643 个字符,预计需要花费 17 分钟才能阅读完成。

本篇文章为大家展示了如何有效地跟踪 Bug 记录带有详细参数值的 SQL,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

在实际开发工作中,可能需要很多调试的工作,通过调试,也许能够更好地发现程序的具体问题。

假想下,今天 QA 同事给你报了一个 bug,当然她们不会给出具体的原因,而仅仅是给出 Bug 导致的果,那么你如何 fix 这个 bug 了,显然每个人处理问题的方法是不一样的,但是大致会这样:问 QA,为什么会出现这样的 Bug 啊、在什么时间什么地方出现的…? 过后你可能会装作思考状,良久后说,这不是我们的问题,是部署的问题,是 DB 的问题…当然你还可以聊聊天了(一般来说 QA 都是 MM 了 ^_^)…

当然这不是优秀且富有激情的程序员干的事情(也许你就是这样,不过没关系,也许大家或多或少地时候都在做同样的事情),理想的情况是能够根据 QA MM 的叙述,加上查找有用的日志,能够重现并解决 Bug,如果可以的话,可以和 MM 聊聊是如何导致这个 Bug 的。

在大部分的环境下,我们使用的都是很流行的框架,比如说 Hibernate,在查日志的时候,当然你会关心里面 SQL 的记录,不过这些 SQL 也许并没有实际的价值,因为它丢失了很多有用的信息。首先应该知道,如果关心 Hibernate 生成的 SQL,当然需要开启 Show Sql 功能(property name= showSql value= true /),但是你会发现你开启后,Log 记录是类似这样的 insert
… ?  ?  ? 语句,当然这还是有些实用价值的,不过这些语句只能算 SQL 的架子,并不是一个完整可以运行的 SQL,而且确实更多详细的数据,比如这里的“?”是什么。

假如你关心 SQL 里面的问号(?)到底是什么的话,那么请阅读下面的内容?如果你认为这在调试过程中并没有关注过,你可以移步寻找你真正感兴趣的事情,当然还是很欢迎你继续阅读了。

本文介绍的就是这两位主角:log4jdbc 和 jdbcdslog。参考官方文档(官方文档都很详细并全面),你应该能够傻瓜式地配置起这些 Tools,这里我就说说我自己的一些使用建议,并改进增强这些工具的功能。

log4jdbc 主页

http://code.google.com/p/log4jdbc/

配置样例

mysql.database.driver=net.sf.log4jdbc.DriverSpy

mysql.database.url=jdbc:log4jdbc:mysql://127.0.0.1:3306/test?useUnicode=true amp;amp;characterEncoding=utf-8

(其它 log 及依赖包的配置请参考官网)

使用评价

log4jdbc 的优点的是配置简单,支持全部的主流数据库,而且 log 中有原生的 sql(可以直接运行的,这个想法也是我想改造 jdbcdslog 的原因,下文介绍),而且整个 project 代码写的很优美,不过遗憾的是,目前还不支持 DataSource(XA,Pooling), 就因为这点我舍弃了它,现在的项目是 Data Source + XA,真的感觉有点遗憾。不过下载源码你会知道,有份 TODO,作者会在下个版本进行实现,希望 log4jdbc 扩展得越来越实用。官网 wiki 里有篇文章 http://code.google.com/p/log4jdbc/wiki/DataSourceExampleForWebSphere,也是介绍如何能够使用 DataSource
, 我没有深入研究了,如果有兴趣的同学,可以研究下,再开源出来,相应大家会感谢您的辛苦。

Google code 上面确实有 Javaer 实现了(google code projcect  url:
log4jdbc-remix),我拿来用了一下,发现在不改变原配置 (log4jdbc) 的基础上,是有问题的, 错误的具体 issues 请见 http://code.google.com/p/log4jdbc-remix/issues/detail?id=3,后来也就没有使用了(不过我相信作者肯定是成功改造后才共享出来,可能是一些环境问题导致的这个小小问题)。

(相关的配置相信你完全可以通过官网介绍成功地配置好,如果有少少问题的话,可以参考我使用 log4jdbc 的一个小 Demo,请使用 svn check

http://usc.googlecode.com/svn/SSHWithAnnotationDemoUselog4jdbc/)。

jdbcdslog 主页

http://code.google.com/p/jdbcdslog/

配置样例

MySql

mysql.database.driver=org.jdbcdslog.DriverLoggingProxy

mysql.database.url=jdbc\:jdbcdslog\:mysql\://127.0.0.1\:3306/test?useUnicode\=true amp;amp;characterEncoding\=utf-8;targetDriver\=com.mysql.jdbc.Driver

mysql.database.user=root

mysql.database.password=lishunli

mysql.database.maxActive=100

mysql.database.maxIdle=30

mysql.database.maxWait=500

Spring DI

jee:jndi-lookup
id= mssDataSourceActual
jndi-name= ${mss.dataSource.main.jndiName} /

bean
id= mssDataSource
>

property
name= targetDSDirect
ref= mssDataSourceActual
/

/bean

(jndi 的使用,请 google)

Weblogic + Oracle

jdbc-driver-params

 
url jdbc:oracle:thin:@10.100.53.85:1521:cmn?targetDS=oracle.jdbc.xa.client.OracleXADataSource /url

driver-name org.jdbcdslog.ConnectionPoolXADataSourceProxy /driver-name

properties

property

name user /name

value mssapp /value

/property

property

name serverName /name

value 10.100.53.85 /value

/property

property

name portNumber /name

value 1521 /value

/property

property

name SID /name

value cmn /value

/property

/properties

password-encrypted {3DES}ThgsfHr3yB1bfpnD4u/t3A== /password-encrypted

/jdbc-driver-params

JBoss + Oracle

xa-datasource

jndi-name jdbc/coreDataSource /jndi-name

debug true /debug

track-connection-by-tx true /track-connection-by-tx

track-statements true /track-statements

isSameRM-override-value false /isSameRM-override-value

xa-datasource-class org.jdbcdslog.ConnectionPoolXADataSourceProxy /xa-datasource-class

xa-datasource-property
name= URL jdbc:oracle:thin:@10.100.53.85:1521:cmn?targetDS=oracle.jdbc.xa.client.OracleXADataSource /xa-datasource-property

xa-datasource-property
name= User report /xa-datasource-property

xa-datasource-property
name= Password report /xa-datasource-property

min-pool-size 10 /min-pool-size

max-pool-size 200 /max-pool-size

exception-sorter-class-name org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter /exception-sorter-class-name

no-tx-separate-pools/

/xa-datasource

使用评价

支持 DataSource(XA,Pooling)是 jdbcdslog 最大的亮点,还有一个就是作者真的很用心,wiki(文档)写的太详细了,以至于只要看到这份 wiki,就完全能够使用 jdbcdslog;而 log 记录的 sql 的不友好则是它最大的缺憾(我个人是这样认为的,也行你觉得非常完美),如果能像 log4jdbc 那样显示完整的 SQL,那么 jdbcdslog 就很优秀了。

为了向着我自己完美的目标前进,我自己增强了 jdbcdslog,使其满足我(也许还有其他人)的需要。

注:个人觉得不友好的地方是:虽然参数都已经写的很清晰了,但是这个语句并不能地直接使用(拿这个 sql 在控制台上面直接运行),如果需要的话,可能还需要我们一个一个参数进行替换后才可以使用。

(相关的配置可以参考我使用 jdbcdslog 的一个小 Demo,请使用 svn check
http://usc.googlecode.com/svn/SSHWithAnnotationDemo/)。

jdbcdslog-exp 主页

当然,这个就是我 fork 的,主页在 http://code.google.com/p/jdbcdslog-exp/,具体的增强功能和如何使用,可以在这里找到。

配置样例

这个就不贴了,因为 jdbcdslog-exp 并没有修改 jdbcdslog 的配置,使用它的配置就可以了。不过增强功能的会需要少少配置,下面再说。

效果

增强的效果和上面的效果进行对照,你会发现我修改了什么(注意红色下划线部分)

有没有发现这个 sql 是可以直接运行的,而且也去掉了执行时间的日志(复制更加简单,Sql 一般很长了,从“select”再 shift+end 就可以选择一行了),是不是很方便。

新特性和如何使用

1)可以直接填充 SQL 语句的参数,当然生成的日志语句是可以直接复制出来使用的,这个在上面的效果图中已经体现;

数据库的不同,生成的 SQL 会有些不同,比如关键词(特殊字符),在 Oracle 中有 and and \r, \n,\t,SQL Server 中有,
Mysql 中有 and and \ and \r,\n,\t(注:考虑过 like 语句中的特殊字符,不过 jdbcdslog-exp 并没有实现,这部分,一则我觉得使用率比较少,一则如果真的有的话,注意下应该也不是那么困难。),再比如日期格式。那么如何更改数据库类型来选择合适的生成语句,请看:

在 jdbcdslog.properties 文件(这个可以参考原始的文档,或者直接新建 jdbcdslog.properties 配置文件放在 class path 路径下就可以了)中配置

#jdbcdslog driver name.if empty,is oracle(default db)

#you may choose oracle , mysql , sqlserver or empty (Case-insensitive and does not need the double quotes)

jdbcdslog.driverName=oracle

2)可以配置是否显示 SQL 执行的时间,默认不显示,这个默认选择,也在上面效果图中体现了,当然你可以通过下面的配置显示出来。

同样在 jdbcdslog.properties 文件中配置

#jdbcdslog will show elapsed time

jdbcdslog.showTime=true

3)Maven 的支持

Maven 的天下已经或者快要来的,当然要支持了,你可以这样依赖:

dependency
groupId com.googlecode.usc /groupId
artifactId jdbcdslog /artifactId
version 1.0.6.2 /version
/dependency

jdbcdslog-exp 已经放到 Maven 中央仓库里了(如何 deploy 到 maven central repo?请阅读我上篇文章:Maven
Artifacts 如何部署到仓库),为了名称的一致性,选用了 jdbcdslog 作为构建名,而不是 jdbcdslog-exp。

或者 http://jdbcdslog-exp.googlecode.com/files/jdbcdslog-1.0.6.2.jar 通过下载并放到 class
patch 里面即可,更多下载请见 http://code.google.com/p/jdbcdslog-exp/downloads/list,包括源代码和 Javadoc,当然你可以通过 svn checkout 下来,自己在继续改进,svn url 为
http://jdbcdslog-exp.googlecode.com/svn/trunk/。

实际上,这篇博文早就写了个大概,但是被下面的问题一直耽误着:

我使用的是 Weblogic + Oracle(安装在本地其他的机器),使用的是 org.jdbcdslog.ConnectionPoolXADataSourceProxy,但是不知为什么,在某些情况下,就会出现 weblogic 卡着,执行不下去,一段时间后,就会出现超时 (Time Out) 异常,经过很长时间的调试和查看,可能有两个原因造成的:

1)jdbcdslog(jdbcdslog-exp) 本身的 Bug,对处理 datasource 类型没有相应的关闭链接(我猜测);

2)本地 Oracle DB 安装有问题,因为我的同事也发生过这样的情况,不过比我少多了。

不过你不用担心,这种情况还是比较少出现的,还不影响正常的使用(开发阶段)的。如果您知道为什么会出现这种情况或者有类似的问题出现,欢迎讨论。谢谢。

总结或建议

1. 如果要使用 jdbcdslog 或者 jdbcdslog-exp,请先阅读 jdbcdslog’s UserGuide
http://code.google.com/p/jdbcdslog/wiki/UserGuide。

2.jdbcdslog 只是一个独立包,需要 slf4j-api 和 slf4j-log4j12 的支持。

3.Log 中只需要开 statement 的 info,其它的都不需要,如果考虑性能测试的时候,就另当别论了。像这样(log4j.xml):

!– logger: jdbcdslog —

logger
name= org.jdbcdslog.StatementLogger

level
value= INFO /

/logger

logger
name= org.jdbcdslog.ResultSetLogger

level
value= OFF /

/logger

logger
name= org.jdbcdslog.SlowQueryLogger

level
value= OFF /

/logger

logger
name= org.jdbcdslog.ConnectionLogger

level
value= OFF /

/logger

上面关于 JDBC 工具的实现使用的是代理,类似 AOP 思想,都是通过监听(可能说 Spy 更好一点)数据层,获取 JDBC 所带来的数据信息。当然还有很多优秀的工具包能够实现这样的功能,比如 spy6。

上述内容就是如何有效地跟踪 Bug 记录带有详细参数值的 SQL,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注丸趣 TV 行业资讯频道。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-28发表,共计6643字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)