Java – PGBouncer JDBC中的connect_query设置

我正在将PGBouncer配置为我的应用程序的数据库连接池.我也在会话池模式下使用它.

由于某些应用程序要求,我需要在使用每个连接期间保留一个临时表.我目前正在做的是使用connect_query设置来创建我的临时表.

根据文档,此查询“在建立连接后执行”.据我所知,这意味着每次从池中借用连接时都会执行connect_query.

我想避免的是以下情况:

>如果物理连接有,我从池中借用连接
不存在,它将被创建. connect_query将是
执行.
>我将连接返回到池中.
>我再次请求连接到池,让我们假设池重用了步骤1中使用的相同连接并返回它. connect_query再次执行.

UPDATE
我可以看到,当通过JDBC连接到PGBouncer并使用连接执行查询时,每个连接请求都会执行一次connect_query.以下面的java类为例:

public class TestPgbouncerConnectQuery {

  public static void main(String[] args) {
    for (int i = 0; i < 1000; i++) {
      try {
        System.out.println("Iteration: " + i);
        Connection conn = getConnection();
        executeQuery(conn);
        conn.close();
      } catch (SQLException e) {
      }
    }
  }

  private static Connection getConnection() {
    Connection conn = null;
    try {
      Properties properties = new Properties();
      properties.setProperty("user", "myuser");
      properties.setProperty("password", "mypass");
      Class.forName("org.postgresql.Driver");
      conn = DriverManager.getConnection("jdbc:postgresql://localhost:6432/mydatabase", properties);
      conn.setAutoCommit(false);
    } catch (Exception e) {
    }
    return conn;
  }

  private static void executeQuery(Connection conn) {
    PreparedStatement ps = null;
    try {
      ps = conn.prepareStatement("select 1");
      ps.executeQuery();
    } catch (Exception e) {
    } finally {
      if (ps != null) {
        try {
          ps.close();
        } catch (Exception e) {
        }
      }
    }
  }
}

执行此代码后,如果我查询到pg_stat_statements:

select * from pg_stat_statements

我可以看到每个检索到的连接都执行了一次connect_query.但是如果我评论这一行,就不要在每次迭代时执行查询:

executeQuery(conn);

我无法重现这个问题,即在pg_stat_statements中,每个检索到的连接都不会出现一次connect_query.

最佳答案 我认为它就像你需要它一样工作:

-bash-4.2$psql -p 6432 -d t -U v -h 1.1.1.1
Password for user v:
psql (9.3.18)
Type "help" for help.

t=> select * from tt;
 i
---
(0 rows)

t=> insert into tt select 1;
INSERT 0 1
t=> select * from dblink('port=6432 dbname=t hostaddr=1.1.1.1 user=v password=v','select i from tt') as t(i int);
 i
---
(0 rows)

t=> select i from tt;
 i
---
 1
(1 row)

t=> select * from dblink('port=5432 dbname=mon hostaddr=1.1.1.1 user=v password=v','select i from tt') as t(i int);
ERROR:  relation "tt" does not exist
CONTEXT:  Error occurred on dblink connection named "unnamed": could not execute query.
t=> select current_database();
 current_database
------------------
 mon
(1 row)

pgbouncer上的新会话会静默创建临时表(不存在任何异常)并可用于新会话 – 无需重新创建或检查.在会话池模式中,不同会话的内容是不同的.如果我没有连接pgbouncer临时表不存在…

这是配置:

t=> \! head -2 /etc/pgbouncer/pgbouncer.ini
[databases]
t = host=/var/run/postgresql dbname=mon connect_query = 'create temp table tt(i int)'

UPDATE

而现在我认为它不适合你,因为它创建了“phisical connect”表,而不是从池中获取连接.这是证据:

-bash-4.2$psql -p 6432 -d t -U v -h localhost
Password for user v:
psql (9.3.18)
Type "help" for help.

t=> insert into tt select 5;
INSERT 0 1
t=> \q
-bash-4.2$psql -c "select query from pg_stat_activity"
               query
------------------------------------
 DISCARD ALL
 select query from pg_stat_activity
(2 rows)

-bash-4.2$psql -p 6432 -d t -U v -h localhost
Password for user v:
psql (9.3.18)
Type "help" for help.

t=> insert into tt select 5;
ERROR:  relation "tt" does not exist
LINE 1: insert into tt select 5;
                    ^

在从池中提供连接之前它会丢弃所有 – 从而丢弃所有临时表.这就是为什么我在两个会话上面的代码都有自己的表,而最新的例子 – 不是.因为在连接关闭表被删除,会话回到池.所以在下一次连接时没有启动新的连接,但是旧的重用 – 并且表已经没有…

点赞