现在的位置: 首页 > 数据库 > 正文

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

2018年08月07日 数据库 ⁄ 共 7297字 ⁄ 字号 评论关闭

更有效地跟踪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,\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>

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,我会及时处理的,谢谢。

抱歉!评论已关闭.