PostgreSQL JDBC Driver的logUnclosedConnections配置不生效如何解决
为什么logUnclosedConnections没有生效
PostgreSQL JDBC驱动的logUnclosedConnections功能依赖PgConnection类的finalize()方法触发:只有当未主动调用close()的连接对象被垃圾回收器回收时,才会输出未关闭连接的警告日志。你遇到的问题是典型的GC触发时机、等待时间不足、日志配置的问题。
具体修改方案
- 延长GC后的等待时间:你当前只等待1毫秒,完全不够GC运行和
finalize()方法执行,建议改成等待3-5秒,比如Thread.sleep(5000)。 - 明确配置JUL日志输出规则:你虽然配置了JDBC参数的
loggerLevel=DEBUG,但JDK自带的java.util.logging默认可能限制了org.postgresql包的日志输出级别,在代码最开头添加以下配置确保警告日志可以输出:
import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; // 类加载后第一时间执行 static { Logger pgLogger = Logger.getLogger("org.postgresql"); pgLogger.setLevel(Level.ALL); ConsoleHandler consoleHandler = new ConsoleHandler(); consoleHandler.setLevel(Level.ALL); pgLogger.addHandler(consoleHandler); }
- 增大GC回收概率:可以循环创建多个未关闭的连接,每个连接使用完后立刻置为
null,不要等最后才置空,避免这些连接还在作用域内被GC判定为存活对象。 - 不要依赖单次
System.gc()调用:可以连续调用2-3次System.gc(),间隔几百毫秒,提升Full GC触发的概率。
测试代码示例
public static void main( String[] args ) throws Exception { // 日志配置 Logger pgLogger = Logger.getLogger("org.postgresql"); pgLogger.setLevel(Level.ALL); ConsoleHandler consoleHandler = new ConsoleHandler(); consoleHandler.setLevel(Level.ALL); pgLogger.addHandler(consoleHandler); Properties dbProps = new Properties(); dbProps.setProperty( "user", "postgres" ); dbProps.setProperty( "password", "AuR0ra$dba#$" ); dbProps.setProperty( "logServerErrorDetail", "true" ); dbProps.setProperty( "logUnclosedConnections", "true" ); dbProps.setProperty( "loggerLevel", "DEBUG" ); // 循环创建多个未关闭的连接 for (int i = 0; i < 5; i++) { Connection conn = DriverManager.getConnection( "jdbc:postgresql://devdbmaster.koncert.com:5499/dev_koncert_v10.5", dbProps ); PreparedStatement pstmt = conn.prepareStatement( "select count(*) from cl.users limit 10" ); ResultSet rSet = pstmt.executeQuery(); while ( rSet.next() ) { System.out.println( "count is " + rSet.getInt( 1 ) ); } // 用完立刻置空,脱离作用域 conn = null; Thread.sleep(10); } // 多次触发GC for (int i = 0; i < 3; i++) { System.gc(); Thread.sleep(1000); } // 最终等待finalize执行 Thread.sleep(3000); }
运行以上代码就能看到org.postgresql.jdbc.PgConnection输出的未关闭连接警告日志。
内容的提问来源于stack exchange,提问作者Ravi MCA
相关产品推荐
相关产品推荐

