李顺利
随笔-50  评论-170  文章-0  trackbacks-0

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

李顺利

目录

更有效地跟踪Bug——记录带有详细参数值的SQL. 1

引子... 2

log4jdbc. 3

主页... 3

配置样例... 3

效果... 4

使用评价... 5

jdbcdslog. 6

主页... 6

配置样例... 6

效果... 9

使用评价... 10

jdbcdslog-exp. 11

主页... 11

配置样例... 11

效果... 11

新特性和如何使用... 12

胡言乱语... 14

总结或建议... 14

 

引子

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

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

本文介绍的就是这两位主角:log4jdbcjdbcdslog。参考官方文档(官方文档都很详细并全面),你应该能够傻瓜式地配置起这些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及依赖包的配置请参考官网)

效果

clip_image002

使用评价

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" class="org.jdbcdslog.ConnectionPoolXADataSourceProxy">

        <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>

 

效果

clip_image004

使用评价

支持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的配置,使用它的配置就可以了。不过增强功能的会需要少少配置,下面再说。

效果

增强的效果如下:

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

clip_image006

 

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

新特性和如何使用

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

数据库的不同,生成的SQL会有些不同,比如关键词(特殊字符),在Oracle中有' and & and \r, \n,\tSQL 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>

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

5.  当然你如果对Git感兴趣的话,你可以clone 或者 fork  git://github.com/usc/jdbcdslog.git (from https://github.com/usc/jdbcdslog)

6.  如果你有什么问题,非常欢迎通过Email(lishunli.me@gmail.com) 联系我,或者QQ:506817493, 或者微博@李顺利Me(http://weibo.com/lishunli)

亦或者请帮忙在http://code.google.com/p/jdbcdslog-exp/issues/list 里面创建Issues,我会及时处理的,谢谢。

 

顺利更新于2011125



博客中的一些下载已经放到了百度云了,请根据需要下载。【点我去百度云下载】

最后弱弱地说一下,如果可以的话,转载请提供出处( ),谢谢。
posted on 2011-12-05 01:04 李顺利 阅读(4661) 评论(6)  编辑  收藏

评论:
# re: 更有效地跟踪Bug&mdash;&mdash;记录带有详细参数值的SQL[未登录] 2011-12-07 17:10 | tbw
编辑这么好的文章,还真花时间。。支持  回复  更多评论
  
# re: 更有效地跟踪Bug&mdash;&mdash;记录带有详细参数值的SQL 2012-04-10 15:29 | 贾晓峰
很不错啊。我还准备在自己项目中重新写下1.0.5的版本呢。用你fork的正好满足了我的需求。可能中国人的想法就是不一样。哈哈  回复  更多评论
  
# re: 更有效地跟踪Bug&mdash;&mdash;记录带有详细参数值的SQL 2012-04-10 18:12 | 李顺利
@贾晓峰
一切为了方便自己  回复  更多评论
  
# re: 更有效地跟踪Bug&mdash;&mdash;记录带有详细参数值的SQL 2013-12-21 11:10 | 最代码
db层就有完整的sql输出解决方案,在业务层做这个处理是否复杂了?  回复  更多评论
  
# re: 更有效地跟踪Bug&mdash;&mdash;记录带有详细参数值的SQL 2013-12-21 13:05 | 李顺利
@最代码
1. 请问db层完整的sql输出解决方案是如何完成的,我学习下
2. 这个是业务层处理的吗?  回复  更多评论
  
# re: 更有效地跟踪Bug&mdash;&mdash;记录带有详细参数值的SQL 2013-12-23 16:26 | 最代码
@李顺利
我总结分享了一份代码,你参考下:http://www.zuidaima.com/share/1618579475975168.htm  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: