李順利
          隨筆-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 李順利 閱讀(4676) 評論(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  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 固镇县| 郓城县| 河池市| 柏乡县| 定兴县| 安义县| 读书| 宣武区| 偃师市| 遵义县| 赤水市| 宣城市| 芷江| 瓮安县| 阜宁县| 民权县| 沙坪坝区| 呈贡县| 双牌县| 南雄市| 舞阳县| 博罗县| 耒阳市| 芜湖县| 霍州市| 博湖县| 南川市| 泰顺县| 噶尔县| 长岛县| 育儿| 婺源县| 平谷区| 宁都县| 隆德县| 突泉县| 通山县| 师宗县| 谢通门县| 梨树县| 连云港市|