我有一个 mod_perl2.0.4 / Apache2.2 Web 应用程序在 CentOS 6.4 和 PostgreSQL 9.0 上运行。
直到最近,我才进行了这样的设置FATAL: sorry, too many clients already
: Apache::DBI 和 DBI->connect_cached 用于所有连接,即使在我是唯一用户的开发区域中,它也开始提供。
为了调试它,我删除了对 Apache::DBI 的所有引用,升级到最新的 DBI,并将所有出现的 connect_cached 替换为普通的 DBI->connect。现在在我看来,建立的联系少了一些,然后就离开了<IDLE>
。然而,我意识到我并没有在我的所有语句句柄上调用 disconnect(),因为它听起来像在 Apache::DBI 下它不会产生任何影响。
我的连接当前以同一个用户的身份连接,然后通过 SET SESSION AUTHORIZATION 降低他们的权限。我这样做是因为其他一些使用数据库的应用程序允许密码登录,这可以将凭据直接传递给数据库,但是这个特定的网络应用程序使用荣誉系统登录屏幕,您只需单击您的姓名即可登录。因此,它目前已为未来的安全做好准备,但也提供了便利。此外,历史等数据库触发器依赖于正确设置会话用户来跟踪谁做了什么。
因为我担心数据库句柄被错误的会话用户重用,所以我传递{ private_user_login => $login_role_name, PrintError => 0, RaiseError => 1, AutoCommit => 1}
给 connect_cached 以按用户区分每个连接。但是由于我总是在连接后立即设置会话授权,所以我认为所有private_user_login
哈希所做的都是使对于给定的 Apache 进程,如果最终创建和闲置的数据库连接数可能至少与用户数一样多每个用户都设法随机使用给定的 Apache 进程。同时,因为我没有断开任何手柄,它们最终会用完。
我的问题是,取出private_user_login
使所有连接句柄看起来相同,减少打开的连接数量是否安全,或者是否有可能在中间重新使用连接句柄脚本(在设置会话用户之后)由不同的用户,从而创建一个竞争条件?此外,尽管 Apache::DBI 的文档说我不需要删除 disconnect()
调用,但我是否应该在每个脚本的末尾都有这样的调用,以便 Apache::DBI 可以决定是否断开连接?
换句话说,如果没有我的私有连接变量,当下一个 Apache::DBI->connect() 重用现有连接时,SET SESSION AUTHORIZATION 的效果是否仍然存在?如果是这样,当一个请求当前正在执行但当前未使用数据库句柄时,是否有可能另一个请求重新使用连接?