请务必阅读下面这个答案 https://stackoverflow.com/a/11454173/168868,其中详细介绍了缓解此处列出的问题的方法。
与任何其他执行持久连接的 PHP 数据库接口一样,使用 PDO 也存在同样的缺点:如果您的脚本在数据库操作过程中意外终止,则获取剩余连接的下一个请求将从失效脚本停止的位置继续。连接在进程管理器级别(Apache for mod_php,当前的 FastCGI 进程,如果您使用 FastCGI 等)保持打开状态,而不是在 PHP 级别,并且 PHP 不会告诉父进程让连接在以下情况终止:脚本异常终止。
如果死脚本锁定了表,则这些表将保持锁定状态,直到连接终止或获取连接的下一个脚本本身解锁表。
如果死脚本位于事务中间,则可能会阻塞多个表,直到死锁计时器启动为止,即使如此,死锁计时器也可以杀死较新的请求,而不是导致问题的较旧的请求。
如果失效脚本处于事务中间,则获取该连接的下一个脚本也会获取事务状态。很可能(取决于您的应用程序设计)下一个脚本实际上可能不会尝试提交现有事务,或者在不应该提交的时候提交,或者在不应该提交的时候回滚。
这只是冰山一角。通过在每个脚本请求的脏连接后始终尝试清理,可以在一定程度上缓解这种情况,但这可能会很痛苦,具体取决于数据库。除非您已确定创建数据库连接为瓶颈的一件事在你的脚本中(这意味着你已经使用xdebug http://www.xdebug.org/ and/or xhprof http://pecl.php.net/package/xhprof), 你应该not将持久连接视为解决任何问题的方法。
此外,大多数现代数据库(包括 PostgreSQL)都有自己首选的执行连接池的方法,这些方法没有普通的基于 PHP 的持久连接所具有的直接缺点。
为了澄清一点,我们在工作场所使用持久连接,但不是出于选择。我们当时遇到的是weird连接行为,从我们的应用程序服务器到数据库服务器的初始连接正在进行exactly三秒钟,而本应该只需要零点几秒。我们认为这是一个内核错误。我们放弃尝试对其进行故障排除,因为它是随机发生的,无法按需重现,而且我们的外包 IT 没有具体的能力来追踪它。
无论如何,当仓库里的人正在处理几百个传入的零件,并且每个零件需要三秒半而不是半秒时,我们必须在他们绑架我们所有人并让我们帮助他们之前采取行动。因此,我们对我们自己开发的 ERP/CRM/CMS 怪物进行了一些修改,并亲身体验了持久连接的所有可怕之处。我们花了weeks追踪所有看似随机发生的微妙小问题和奇怪行为。事实证明,我们的用户努力从我们的应用程序中挤出的那些每周一次的致命错误导致了锁定的表、放弃的交易和其他不幸的不稳定状态。
这个悲伤的故事有一个道理:它以性能的名义打破了我们从未想过会打破的东西。这种权衡是不值得的,我们热切地等待着有一天我们可以切换回正常连接而不会引起用户的骚乱。