PostgreSQL jdbc driver的一个不完善之处-阿里云开发者社区

开发者社区> 数据库> 正文

PostgreSQL jdbc driver的一个不完善之处

简介: 公司一个产品在上线到云以后,运行一段时间就会提示获取数据库连接失败,用 select * from pg_stat_activity; 查看所有连接,发现有很多连接最后一次执行的SQL语句是 SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typspace = n.oid)  WHERE n.nspname  != 'pg_toast',经确认在程序中没有任何一处执行了该SQL。

公司一个产品在上线到云以后,运行一段时间就会提示获取数据库连接失败,用 select * from pg_stat_activity; 查看所有连接,发现有很多连接最后一次执行的SQL语句是 SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typspace = n.oid)  WHERE n.nspname  != 'pg_toast',经确认在程序中没有任何一处执行了该SQL。

我把 SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typspace = n.oid)  WHERE n.nspname  != 'pg_toast' 这段SQL在postgresql中执行,发现报错,不能通过。

后来经过仔细排查,原来是PostgreSQL的jdbc驱动里的一个不完善之处。


在PostgreSQL jdbc驱动的源码里,有一个PgDatabaseMetaData.java,在里边有一个getTypeInfo()方法调用了类似的SQL,PgDatabaseMetaData.java中的SQL定义如下:

    String sql;
    sql = "SELECT t.typname,t.oid FROM pg_catalog.pg_type t"
          + " JOIN pg_catalog.pg_namespace n ON (t.typnamespace = n.oid) "
          + " WHERE n.nspname  != 'pg_toast'";

    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery(sql);

该段SQL语句在我的postgresql中是可以执行的,返回的是所有类型和表名。

经过仔细比对,两个SQL有细微差别,我的环境里未关闭的连接执行的SQL中是ON (t.typspace = n.oid),而jdbc驱动中执行的是ON (t.typnamespace = n.oid),是字段名称不一样!

我用的jdbc驱动的版本是9.4.1212,而上述源码的版本是42.1.1,估计是新版本的驱动是针对较新版本的postgresql设计的,而新版本的数据库中pg_type表将原typespace字段改名为typenamespace,导致了SQL语句执行失败。

而getTypeInfo()方法中并没有在finally{}语句块中关闭statement,也许这个错误会导致后续的一些错误。


更新PostgreSQL的jdbc驱动到最新版本,连接泄露的问题没有再出现。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章