1. 程式人生 > >PostgreSQL分頁查詢引發的思考:OutOfMemoryError

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

今天先到這兒吧,下次繼續分享^_^