当对一个数据库而不是另一个数据库使用 pgbouncer 时,PDO 会抛出关于 "trust" 身份验证的连接错误。设置相同

PDO throws connection error about "trust" authentication when using pgbouncer for one database, but not another. Settings are identical

这个问题让我抓狂。我有一个连接到 postgresql 数据库的 PHP 脚本,我有用于连接池的 pgbouncer 运行。

我已经使用两个数据库对其进行了测试,当我直接连接时它对两个数据库都工作得很好。这是我的连接代码:

        $dbuser='db1'; $dbpass='db1'; $dbname='db1';

        $dsn="pgsql:port=5432;host=/var/run/postgresql;dbname=$dbname";

        $options = [
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES   => false,
        ];
        try {
                $pg_pdo=new PDO($dsn, $dbuser, $dbpass, $options); 
        } catch (\PDOException $e) {
                throw new \PDOException($e->getMessage(), (int)$e->getCode());
        }

此代码,使用 db1,无论我保留端口 5432 还是将端口更改为 6432,都可以正常工作。当我将数据库名称、用户和密码更改为 db2 时,它在端口 5432 上也能正常工作。

但是当我连接到第二个数据库时并且将端口设置为6432,我得到以下错误:

PHP Fatal error:  Uncaught PDOException: SQLSTATE[08006] [7] ERROR:  "trust" authentication failed

现在,我已经检查了我的 /etc/pgbouncer/pgbouncer.ini,它包含以下行:

[databases]
* =

这意味着任何数据库的连接信息只是被转发。文件中既没有提到 db1 也没有提到 db2。

此外,我的 /var/lib/pgsql/11/data/pg_hba.conf 文件:

# "local" is for Unix domain socket connections only
local   all              postgres                                peer
local   db1              db1                                     md5
local   db2              db2                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            ident
host    replication     all             ::1/128                 ident

是的,我已经重新启动了 pgbouncer.service 和 postgresql-11.service。

我一辈子都弄不明白为什么 PHP 的 PDO 会退回到“信任”身份验证方法,我不希望它这样做,我希望它这样做正常发送密码。

为什么它会使用一个数据库而不是另一个数据库?这是 db2 角色缺少授予 db1 某种特权的问题,还是数据库有所不同?

如果相关,我的环境是 PHP 7.4,PostgreSQL 11.12 和 pgbouncer 1.15。

我最终自己解决了这个问题。显然还需要编辑 /etc/pgbouncer/userlist.txt 文件:

此文件有 db1 的列表,但没有 db2 的列表。添加第二行(格式为“用户名”“密码”):

"db2" "db2"

但是,这不足以解决问题。显然,我以 root 身份创建了这个文件。它需要由 pgbouncer 拥有,所以这个命令是必要的:

chown pgbouncer:pgbouncer /etc/pgbouncer/userlist.txt

这两项更改解决了问题。感谢 this link for helping me, and for this thread 对 pgbouncer 配置如何工作的更详尽的解释。