gpt4 book ai didi

java - PGBouncer + JDBC 中的 connect_query 设置

转载 作者:搜寻专家 更新时间:2023-11-01 03:32:19 37 4
gpt4 key购买 nike

我正在将 PGBouncer 配置为我的应用程序的数据库连接池。我还在 session 池模式下使用它。

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

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

我想避免的是以下情况:

  1. 如果物理连接可以,我从池中借用一个连接不存在,它将被创建。 connect_query 将是执行。
  2. 我将连接返回到池中。
  3. 我再次请求到池的连接,假设池重用步骤 1) 中使用的相同连接并返回它。 connect_query 再次执行。

更新当通过 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 上的新 session 静默创建临时表(没有异常(exception))并且可用于新 session - 无需重新创建或检查。在 session 池模式中,不同 session 的内容不同。如果我连接不是通过 pgbouncer 临时表不存在...

这里是配置:

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

更新

现在我认为它完全不适合您,因为它在“物理连接”上创建表,而不是在从池中获取连接时创建表。这是证据:

-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;
^

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

关于java - PGBouncer + JDBC 中的 connect_query 设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46825223/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com