PostgreSQL分頁查詢引發的思考:OutOfMemoryError
前段時間遇到一個customer issue,問題現象是這樣,每次客戶通過tomcat查詢DB,都會假死,頁面一直打轉,也無法重新登陸。
登陸後臺發現生成了OutOfMemoryError dump檔案.
問題1:怎麼設定才能在server遇到OutOfMemoryError的時候,生成dump檔案呢?
在JAVA_OPTS中增加引數XX:+HeapDumpOnOutOfMemoryError
參考:Java HotSpot VM Options
http://www.oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html
這裡也順便說一下JVM -X引數和-XX引數的區別:
Options that begin with -X are non-standard (not guaranteed to be supported on all VM implementations), and are subject to change without notice in subsequent releases of the JDK.
Options that are specified with -XX are not stable and are subject to change without notice.
我們知道tomcat是通過catalina.sh指令碼啟動的,我們就開啟catalina.sh看看是否設定了這個引數,如下:
JAVA_OPTS="$JAVA_OPTS -Xmn$WEB_Xmn -Xms$WEB_Xms -Xmx$WEB_Xmx -Xss$WEB_Xss -XX:PermSize=$WEB_PermSize -XX:MaxPermSize=$WEB_MaxPermSize $Compress_Oops -XX:SurvivorRatio=3 -XX:+DisableExplicitGC -XX:CMSInitiatingOccupancyFraction=85
-XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSMaxAbortablePrecleanTime=30000 -XX:+UseFastAccessorMethods -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError"
發現了吧,catalina.sh設定了這個引數,所以當發生OutOfMemoryError錯誤時,就會產生一個dump檔案。
趕緊將dump檔案取過來進行分析。
問題2:什麼是dump檔案,dump檔案應該用什麼工具分析呢?
不急,咱們來逐個回答。dump檔案就是這樣一個檔案java_pid13793.hprof,當然名字會有不同,也就是一個*.hprof字尾名的檔案。一般我們會使用MemoryAnalyzer這個工具來分析。
注意:dump檔案一般比較大,如果發現用MemoryAnalyzer打不開,請調下MemoryAnalyzer.ini中的設定,將-Xmx1024m改成一個更大的值,比如改成-Xmx4096m。
問題3:怎麼分析呢,分析步驟是什麼?
1)第一步開啟dump檔案,選擇Leak Suspects Report
2)選擇比重最大的,檢視其堆疊資訊
如圖,Problem Suspect1佔1.3GB,基本上就是它了。
3)分析堆疊資訊
通過分析堆疊,發現是查詢出了問題,由於搜尋的資料量大,將tomcat的記憶體撐爆了。然後就繼續跟蹤程式碼。
問題4:明明設定了分頁查詢,怎麼還會把記憶體撐爆呢?
搜了PostgreSQL的官網才發現,PostgreSQL和MySQL、SQL Server不同,如果想要其分頁生效,必須將Connect.SetAutoCommit(false)設定false.
// make sure autocommit is off
conn.setAutoCommit(false);
具體的可以參考PostgrsSQL的官網說明:
https://jdbc.postgresql.org/documentation/head/query.html#query-with-cursor
今天先到這兒吧,下次繼續分享^_^