監(jiān)控和剖析數(shù)據(jù)庫操作 -- P6Spy、SQL Profiler、IronTrack SQL 使用簡(jiǎn)介
本文介紹如何在應(yīng)用程序中利用 P6Spy、SQL Profiler、IronTrack SQL 工具來對(duì)數(shù)據(jù)庫操作進(jìn)行監(jiān)控與剖析,從中發(fā)現(xiàn)應(yīng)用系統(tǒng)存在的性能瓶頸,得到相關(guān)的優(yōu)化建議并最終找到相應(yīng)的解決辦法。
![]() |
|
在我們 Java 開發(fā)應(yīng)用程序的過程中,難免會(huì)碰到系統(tǒng)的性能問題,特別在企業(yè)應(yīng)用的開發(fā)過程中,都會(huì)與數(shù)據(jù)庫進(jìn)行打交道。當(dāng)我們碰到數(shù)據(jù)庫性能時(shí),最有效的就是直接跟蹤每一個(gè) SQL 語句的執(zhí)行情況,SQL 語句的優(yōu)化、索引的優(yōu)化往往也是最容易取得最直接的效果的。
下面,我們首先開始介紹 P6Spy 這個(gè)剖析工具,看它是如何無侵入性地進(jìn)行數(shù)據(jù)庫操作的監(jiān)控與剖析。
P6Spy 是一個(gè)可以用來在應(yīng)用程序中攔截和修改數(shù)據(jù)操作語句的開源框架。通過 P6Spy 我們可以對(duì) SQL 語句進(jìn)行攔截,相當(dāng)于一個(gè) SQL 語句的記錄器,這樣我們可以用它來作相關(guān)的分析,比如性能分析。P6Spy 用 Log4J 來記錄 JDBC 調(diào)用的日記信息。
自從 2003 年 11 月 30 日 P6Spy 版本 1.3 發(fā)布后,已經(jīng)被下載超過 19,000 次了。P6Spy 支持 WebSphere、WebLogic、JBoss、Resin 和 Tomcat 等絕大多數(shù)的應(yīng)用服務(wù)器。
首先,你的應(yīng)用系統(tǒng)應(yīng)當(dāng)是基于數(shù)據(jù)庫的,然后你需要去獲取 P6Spy 相關(guān)的文件(在 參考資源 中可以找到下載鏈接,您可以直接下載軟件包)。下面介紹 P6Spy 的安裝與使用的詳細(xì)操作過程:
- 下載 P6Spy 的文件包,也可以下載它的源文件包來研究;
- 把 P6Spy 的 jar 包 p6spy.jar 放到
CLASSPATH
中,如果是 Web 應(yīng)用程序則放在YourWebApp/WEB-INF/lib/
目錄下; - 把 spy.properties 放到
CLASSPATH
目錄下,如果是 Web 應(yīng)用程序放在YourWebApp/WEB-INF/classess/
目錄下,注意不是lib/
目錄 - 修改你應(yīng)用系統(tǒng)中的數(shù)據(jù)庫驅(qū)動(dòng)名稱為 P6Spy 的驅(qū)動(dòng)程序名稱
com.p6spy.engine.spy.P6SpyDriver
其它的全部使用默認(rèn)值,暫時(shí)先都不用修改; - 打開配置文件 spy.properties 文件,找到
realdriver
,把它的值改為你的應(yīng)用系統(tǒng)的真正的數(shù)據(jù)庫驅(qū)動(dòng)名稱; - 運(yùn)行你的應(yīng)用程序或 Web 應(yīng)用程序,可以在 spy.log 里看到 P6Spy 監(jiān)測(cè)到的 SQL 詳細(xì)的執(zhí)行與操作的記錄信息了,包含有完整的 SQL 執(zhí)行參數(shù)。
在 P6Spy 發(fā)布包中,它包含 P6Log 和 P6Outage 兩個(gè)模塊:
- P6Log
P6Log 是用來攔截和記錄任務(wù)應(yīng)用程序的 JDBC 語句的。這個(gè)功能對(duì)于開發(fā)者監(jiān)控 EJB 服務(wù)器上的 SQL 語句執(zhí)行情況尤其有用,可以讓開發(fā)者完成盡可能高效的代碼。同時(shí) P6Spy 的部署是極其簡(jiǎn)單的,而且根本不需要更改任何一行代碼,即對(duì)現(xiàn)有的應(yīng)用是無侵入性的。
realdriver= (your driver) (你的實(shí)際 JDBC 驅(qū)動(dòng)程序名稱) executionthreshold=整數(shù)時(shí)間 (以毫秒為單位)
- P6Outage
P6Outage 專門用來檢測(cè)和記錄執(zhí)行時(shí)間比較長的 SQL 語句,P6Outage 只記錄超過配置條件里時(shí)間的那些信息,并對(duì)可能影響到數(shù)據(jù)庫的運(yùn)行效率減小到最低。
#outagedetection=true|false (是否記錄較長時(shí)間運(yùn)行的語句) #outagedetectioninterval=整數(shù)時(shí)間 (以秒為單位)
簡(jiǎn)單地講,我們可以認(rèn)為 P6Spy 就是一個(gè)代理(Proxy),它只做了一層對(duì) JDBC 驅(qū)動(dòng)的攔截,然后轉(zhuǎn)發(fā)出去,這樣的設(shè)計(jì)與實(shí)際的應(yīng)用程序沒有任何的耦合性,除了在配置中將驅(qū)動(dòng)程序改成 P6Spy 的攔截驅(qū)動(dòng)外,程序其他地方并不需要做任何的改變。這層攔截器除了可能會(huì)給系統(tǒng)帶來略微的性能下降外,對(duì)程序其他方面沒有任何的影響。而相對(duì)于這一點(diǎn)點(diǎn)的性能下降,在開發(fā)環(huán)境中對(duì)于開發(fā)人員來說是無法感覺到,相比它所帶來的好處,完全可以忽略不計(jì)。
圖 1. P6Spy 對(duì)數(shù)據(jù)庫進(jìn)行攔截監(jiān)控的處理過程

如果在你的應(yīng)用程序啟動(dòng)后,卻在 spy.log 文件中發(fā)現(xiàn)了如下的提示信息,那就是驅(qū)動(dòng)程序加載先后的問題了。
<你的程序的數(shù)據(jù)庫驅(qū)動(dòng)名稱> is a real driver in spy.properties, but it has been loaded before p6spy. p6spy will not wrap these connections. Either prevent the driver from loading, or try setting'deregisterdrivers' to true in spy.properties |
請(qǐng)把 spy.properties 配置文件里的 deregisterdrivers=false
改為 deregisterdrivers=true
,重新運(yùn)行即可。
這是因?yàn)橛行?yīng)用系統(tǒng)中會(huì)先于 P6Spy 加載了真正的數(shù)據(jù)庫的驅(qū)動(dòng)程序,導(dǎo)致 P6Spy 無法監(jiān)控到,設(shè)置 deregisterdrivers
為 true
,是顯式地把真正的數(shù)據(jù)庫的驅(qū)動(dòng)程序進(jìn)行反注冊(cè)掉,而采用 P6Spy 的驅(qū)動(dòng)程序。
下表列出了 spy.properties 配置文件中的各配置項(xiàng)的名稱、默認(rèn)值及其意義和相關(guān)注意事項(xiàng):
配置項(xiàng)名稱 | 默認(rèn)值 | 配置項(xiàng)意義及相關(guān)注意事項(xiàng) |
---|---|---|
module.log | com.p6spy.engine.logging. P6LogFactory | 用來攔截和記錄任務(wù)應(yīng)用程序的 JDBC 語句。若無配置或注釋掉則無此功能。 |
module.outage | com.p6spy.engine.outage. P6OutageFactory | 檢測(cè)和記錄執(zhí)行時(shí)間比較長的 SQL 語句。若無配置或注釋掉則無此功能。 |
realdriver | 真正的應(yīng)用系統(tǒng)使用的數(shù)據(jù)庫驅(qū)動(dòng)程序名稱。 | |
realdriver2 | 真正的應(yīng)用系統(tǒng)使用的第二種備用數(shù)據(jù)庫驅(qū)動(dòng)程序名稱。 | |
realdriver3 | 真正的應(yīng)用系統(tǒng)使用的第三種備用數(shù)據(jù)庫驅(qū)動(dòng)程序名稱。 | |
deregisterdrivers | false | 顯示地把真正的數(shù)據(jù)庫的驅(qū)動(dòng)程序進(jìn)行反注冊(cè)掉。取值 true| false |
executionthreshold | P6Log 模塊執(zhí)行時(shí)間設(shè)置,整數(shù)值 (以毫秒為單位),只有當(dāng)超過這個(gè)時(shí)間才進(jìn)行記錄 Log。 | |
outagedetection | false | P6Outage 模塊是否記錄較長時(shí)間運(yùn)行的語句。取值 true| false |
outagedetectioninterval | P6Outage 模塊執(zhí)行時(shí)間設(shè)置,整數(shù)值 (以秒為單位)),只有當(dāng)超過這個(gè)時(shí)間才進(jìn)行記錄 Log。 | |
filter | false | 是否過濾 Log,取值 true| false |
include | 過濾 Log 時(shí)所包含的表名列表,以逗號(hào)分隔。 | |
exclude | 過濾 Log 時(shí)所排除的表名列表,以逗號(hào)分隔。 | |
sqlexpression | 過濾 Log 時(shí)的 SQL 表達(dá)式名稱 | |
autoflush | true | 是否自動(dòng)刷新。取值 true| false |
dateformat | 設(shè)置時(shí)間的格式,也就是用 Java 的 SimpleDateFormat 程序。 | |
includecategories | 顯示指定過濾 Log 時(shí)包含的分類列表,取值為 error,info,batch,debug,statement,commit,rollback,result 的各種組合。 | |
excludecategories | 顯示指定過濾 Log 時(shí)排隊(duì)的分類列表,取值同上。 | |
stringmatcher | 使用正則表達(dá)式來過濾 Log,取值為 com.p6spy.engine.common.GnuRegexMatcher 和 com.p6spy.engine.common.JakartaRegexMatcher | |
stacktrace | false | 打印堆棧跟蹤信息。取值 true| false |
stacktraceclass | 如果 stacktrace=true,則可以指定具體的類名來進(jìn)行過濾。 | |
reloadproperties | false | 監(jiān)測(cè)屬性配置文件是否進(jìn)行重新加載。取值 true| false |
reloadpropertiesinterval | 60 | 屬性配置文件重新加載的時(shí)間間隔,以秒為單位。 |
useprefix | false | 是否加上前綴,設(shè)置為 true,會(huì)加上 p6spy: 作為前綴。取值 true| false |
appender | com.p6spy.engine.logging. appender.FileLogger | 指定 Log 的 appender,與 Log4J 有點(diǎn)同義,取值:com.p6spy.engine.logging.appender.Log4jLogger、com.p6spy.engine.logging.appender.StdoutLogger 和 com.p6spy.engine.logging.appender.FileLogger |
logfile | spy.log | 指定 Log 的文件名,任何適于操作系統(tǒng)的文件。 |
append | true | 指定是否每次是增加 Log,設(shè)置為 false 則每次都會(huì)先進(jìn)行清空。取值 true| false |
log4j.appender.STDOUT | org.apache.log4j.ConsoleAppender | 當(dāng) appender 為 log4j 時(shí)采用的配置,配置如同 Log4J 的相關(guān)配置。 |
log4j.appender.STDOUT.layout | org.apache.log4j.PatternLayout | 同上 |
log4j.appender.STDOUT. layout.ConversionPattern | p6spy - %m%n | 同上 |
log4j.logger.p6spy | INFO,STDOUT | Log 級(jí)別的設(shè)置,取值同 Log4J 的配置 |
realdatasource | 設(shè)置數(shù)據(jù)源 DataSource 的配置名稱。 | |
realdatasourceclass | 設(shè)置數(shù)據(jù)源 DataSource 的類的全稱。 | |
realdatasourceproperties | 設(shè)置數(shù)據(jù)源 DataSource 的屬性,以分號(hào)分隔。 | |
jndicontextfactory | 設(shè)置 JNDI 數(shù)據(jù)源的 NamingContextFactory。 | |
jndicontextproviderurl | 設(shè)置 JNDI 數(shù)據(jù)源的提供者的 URL。 | |
jndicontextcustom | 設(shè)置 JNDI 數(shù)據(jù)源的一些定制信息,以分號(hào)分隔。 |
![]() ![]() |
![]()
|
SQL Profiler 是一個(gè)由 Jahia.org 提供的基于 P6Spy 引擎的快速剖析工具,用來統(tǒng)計(jì) SQL 查詢語句以便了解哪里是性能瓶頸,在哪里創(chuàng)建索引或者采取相應(yīng)的辦法才能提高效率,并且能根據(jù) SQL 查詢語句的情況幫你生成合適的索引腳本。
這個(gè)小工具可以實(shí)時(shí)地顯示數(shù)據(jù)庫查詢的情況,通過集成的 SQL 解析器,在訪問大多數(shù)表與列上面建立統(tǒng)計(jì)分析,并生成索引腳本。當(dāng)然,其它的信息也會(huì)進(jìn)行收集和顯示,比如:?jiǎn)蝹€(gè)數(shù)據(jù)庫請(qǐng)求的時(shí)間、一類請(qǐng)求的時(shí)間以及所有請(qǐng)求的時(shí)間。因此,可以有效地通過視圖的排序來檢測(cè)數(shù)據(jù)的性能問題所在。這個(gè)工具對(duì)于大量的需要進(jìn)行分析的請(qǐng)求是非常有用的,而不是人工一個(gè)個(gè)地去做分析。當(dāng)你需要知道比如對(duì)相同的表和列進(jìn)行訪問但是采用不同的查詢值時(shí),這種分組的查詢可以用建立在 ANTLR 上的 SQL 解析器進(jìn)行分析。
首先,你的應(yīng)用系統(tǒng)同樣也應(yīng)當(dāng)是基于數(shù)據(jù)庫的,然后你需要去獲取 SQL Profiler 相關(guān)的文件(在 參考資源 中可以找到下載鏈接,您可以直接下載軟件包)。下面介紹 SQL Profiler 的安裝與使用的詳細(xì)操作過程:
- 下載 SQL Profiler 的文件包進(jìn)行安裝;
- 把 p6spy.jar 及 sqlprofiler.jar 放到
CLASSPATH
中,如果是 Web 應(yīng)用程序則放在YourWebApp/WEB-INF/lib/
目錄下; - 把 spy.properties 放到
CLASSPATH
目錄下,如果是 Web 應(yīng)用程序就放在YourWebApp/WEB-INF/classess/
目錄下,注意不是lib/
目錄; - 修改你應(yīng)用系統(tǒng)中的數(shù)據(jù)庫驅(qū)動(dòng)名稱為 P6Spy 的驅(qū)動(dòng)程序名稱
com.p6spy.engine.spy.P6SpyDriver
其它的全部使用默認(rèn)值,暫時(shí)不用修改; - 打開 spy.properties 文件,把
realdriver
的值改為你的程序的數(shù)據(jù)庫驅(qū)動(dòng)名稱; - 注意要先運(yùn)行
java -jar sqlprofiler.jar
來啟動(dòng) SQL Profiler,并成功看到啟動(dòng)界面; - 然后再啟動(dòng)你的應(yīng)用程序或服務(wù)器,并開始進(jìn)行正常的系統(tǒng)請(qǐng)求處理操作;
- 這樣就可以在 SQL Profiler 圖形化的界面上看到結(jié)果并進(jìn)行分析了。
經(jīng)過一段時(shí)間的系統(tǒng)運(yùn)行后,點(diǎn)擊 Pause 按鈕停止攔截,可以得到分析結(jié)果如下圖:
圖 2. SQL Profiler 的分析結(jié)果 Profiler 視圖

接著,可以切換到 Loggers 視圖,這是 Lgger 視圖的信息:
圖 3. SQL Profiler 的分析結(jié)果 Logger 視圖

當(dāng)然,也可以切換到 Analysis 視圖,這是 Analysis 視圖的分析結(jié)果信息:
圖 4. SQL Profiler 的分析結(jié)果 Analysis 視圖

在經(jīng)過分析后,我們可以直接通過 SQLProfiler 提交的保存按鈕,直接導(dǎo)出應(yīng)當(dāng)進(jìn)行數(shù)據(jù)庫優(yōu)化的建議的索引腳本,通過查看索引腳本,我們可以看到創(chuàng)建索引的詳細(xì) SQL 腳本,這樣,我們就可以非常方便地進(jìn)行數(shù)據(jù)庫調(diào)優(yōu)了。
最后一個(gè)需要注意的問題就是需要先啟動(dòng) SQLProfiler,然后再啟動(dòng)應(yīng)用程序或者 Tomcat 等應(yīng)用服務(wù)器。這是因?yàn)?SQLProfiler 默認(rèn)使用的是 Log4j 的 SocketAppender,所以要先啟動(dòng)。否則,會(huì)因你的應(yīng)用程序或應(yīng)用服務(wù)器中的 Web 應(yīng)用之類的因連接不到 Socket 的服務(wù)器(SQLProfiler 相當(dāng)于 Socket 的服務(wù)器)而發(fā)生錯(cuò)誤,可以通過 SQL Profiler 控制界面最下面的連接狀態(tài)就可以知道是否有程序連接上來。
圖 5. SQL Profiler 處于非連接狀態(tài)

圖 6. SQL Profiler 處于連接狀態(tài)

![]() ![]() |
![]()
|
IronEye,一個(gè)專注于 JDBC 性能的監(jiān)控和測(cè)試的開源項(xiàng)目,它包含有三個(gè)工具:IronEye SQL,IronEye Cache,IronTrack SQL。其中,IronEye SQL 用于監(jiān)測(cè) Java 應(yīng)用和數(shù)據(jù)庫服務(wù)器之間查詢開銷的時(shí)間,診斷在性能方面是否存在著相關(guān)問題,讓開發(fā)人員在測(cè)試之前就能發(fā)現(xiàn)問題。IronEye 于 2003 年 10 月 1 日開始基于 Apache Software License 發(fā)布。
IronEye SQL 這個(gè)輕量級(jí)的 Java 工具提供所有流動(dòng)在數(shù)據(jù)庫與應(yīng)用程序之間的 SQL 統(tǒng)計(jì)信息并用多張圖表展現(xiàn),可以快速優(yōu)化程序的性能。
IronGrid 相對(duì)于 Continuous Integration 提出了 Continuous Performance 的概念,即在項(xiàng)目開發(fā)過程中隨時(shí)關(guān)注性能問題,而不是傳統(tǒng)的出了問題再解決的方案。
IronGrid 在應(yīng)用程序?qū)?shù)據(jù)庫的操作上的 Continuous Performance 是通過 IronTrack SQL 進(jìn)行體現(xiàn)的。IronTrack SQL 能通過對(duì) JDBC 的包裝來攔截應(yīng)用程序?qū)?shù)據(jù)庫的請(qǐng)求,完成性能監(jiān)控。IronTrack SQL 的好處在于不需要修改任何代碼或者在數(shù)據(jù)庫端安裝任何程序,只需要在測(cè)試時(shí)把依賴的 JDBC 替換就可以了。
首先,你的應(yīng)用系統(tǒng)同樣也應(yīng)當(dāng)是基于數(shù)據(jù)庫的,然后你需要去獲取 IronTrack SQL 相關(guān)的文件(在 參考資源 中可以找到下載鏈接,您可以直接下載軟件包)。下面介紹 IronTrack SQL 的安裝與使用的詳細(xì)操作過程:
- 下載 IronTrack SQL 的文件包進(jìn)行安裝;
- 把 irontracksql.jar, p6spy.jar 和 log4j-1.2.8.jar 放到
CLASSPATH
中,如果是 Web 應(yīng)用程序則放在YourWebApp/WEB-INF/lib/
目錄下; - 把 spy.properties 放到
CLASSPATH
目錄下,如果是 Web 應(yīng)用程序就放在YourWebApp/WEB-INF/classess/
目錄下,注意不是lib/
目錄; - 修改你程序的數(shù)據(jù)庫驅(qū)動(dòng)名稱為 P6Spy 的驅(qū)動(dòng)程序名稱
com.p6spy.engine.spy.P6SpyDriver
其它的都不用更改; - 打開配置文件 spy.properties 文件,找到
realdriver
,把它的值改為你的應(yīng)用系統(tǒng)的真正的數(shù)據(jù)庫驅(qū)動(dòng)名稱; - 設(shè)置監(jiān)聽端口號(hào)
monitorport=2000
; - 先運(yùn)行
java -jar irontracksql.jar
來啟動(dòng) IronTrack SQL; - 再啟動(dòng)你的應(yīng)用程序或服務(wù)器;
- 可以在 IronTrack SQL 圖形化的界面上看到結(jié)果并進(jìn)行分析了。
點(diǎn)擊“Config”按鈕就可以設(shè)置主機(jī)名、端口與刷新的時(shí)間(毫秒為單位)。根據(jù)你的服務(wù)器與端口的不同而進(jìn)行相應(yīng)地改變,下面以本地和 2000 端口,刷新時(shí)間為 500 毫秒為示例。設(shè)置完成后,確定,點(diǎn)擊“Connect”就可以連接應(yīng)用系統(tǒng)并進(jìn)行監(jiān)測(cè)與分析了,當(dāng)要停止分析時(shí),只要點(diǎn)擊“Disconnect”按扭即可立刻停止分析了。
在分析的過程中,我們可以根據(jù)需要點(diǎn)擊“Purge”按鈕,它可以清除目前所監(jiān)測(cè)到的內(nèi)容,然后重新進(jìn)行記錄監(jiān)測(cè)信息,很方便地進(jìn)行重新開始。
圖 7. IronTrack SQL 連接示例

經(jīng)過一段時(shí)間的系統(tǒng)運(yùn)行后,我們可以直接得到分析的結(jié)果與相應(yīng)的圖形分析示例。相關(guān)的信息顯示如下:
圖 8. IronTrack SQL 分析結(jié)果

- Count 列顯示 SQL 語句的調(diào)用次數(shù);
- Avg Time 列顯示 SQL 語句的執(zhí)行平均時(shí)間;
- Max Time 列顯示 SQL 語句花費(fèi)的最高時(shí)間;
- SQL 列顯示真正執(zhí)行的 SQL 語句內(nèi)容。
同時(shí)也可以通過設(shè)置過濾條件來顯示指定條件的結(jié)果,比如:只關(guān)注平均調(diào)用次數(shù)大于 100 次 的結(jié)果。點(diǎn)擊“Filtering”左邊的小三角圖標(biāo),可以顯示如下的過濾條件設(shè)置欄目:
圖 9. IronTrack SQL 設(shè)置相關(guān)的過濾條件

設(shè)置完成后,點(diǎn)擊“Apply Filter”按鈕即可以獲取所需要的相關(guān)結(jié)果了。這樣可以更加方便地集中精力進(jìn)行所需要的內(nèi)容分析,可以更加方便快速地定位到問題的所在之處,然后進(jìn)行解決。
![]() ![]() |
![]()
|
通過使用 P6Spy、SQL Profiler、IronTrack SQL 工具,我們可以無侵入已有的應(yīng)用系統(tǒng)而有效地進(jìn)行數(shù)據(jù)庫操作的監(jiān)控與剖析,為發(fā)現(xiàn)系統(tǒng)的性能瓶頸,尋找系統(tǒng)的性能調(diào)優(yōu)提供了相當(dāng)便利的方法。
學(xué)習(xí)
- P6Spy 站點(diǎn):提供數(shù)據(jù)庫性能監(jiān)控和剖析工具。
- SQL Profiler 站點(diǎn):提供的基于 P6Spy 引擎的數(shù)據(jù)庫快速剖析工具 SQL Profiler。
- Java 技術(shù)專區(qū):尋找 Java 編程各方面的技術(shù)文章。
獲得產(chǎn)品和技術(shù)
- 下載 P6Spy 軟件包。
- 下載 SQL Profiler 軟件包。
- 下載 IronTrack SQL 軟件包。
posted on 2009-08-12 14:48 小卓 閱讀(203) 評(píng)論(0) 編輯 收藏 所屬分類: datebase