请务必阅读以下答案,其中详细介绍了缓解此处概述的问题的方法。
使用PDO与进行持久连接的任何其他PHP数据库接口一样,也存在相同的缺点:如果您的脚本在数据库操作过程中意外终止,则下一个获得剩余连接的请求将在死脚本停止的地方继续。连接在进程管理器级别(Apache for mod_php,如果使用的是FastCGI,则为当前的FastCGI进程,等等)保持打开状态,而不是在PHP级别保持打开状态,并且PHP不会告诉父进程何时终止连接脚本异常终止。
如果死脚本锁定了表,则这些表将保持锁定,直到连接死亡或下一个获得连接的脚本将表本身解锁为止。
如果死脚本位于事务中间,则可能会阻塞多个表,直到死锁计时器开始运行为止,即使这样,死锁计时器也可以杀死较新的请求,而不是导致问题的较旧的请求。
如果无效脚本位于事务中间,则下一个获得该连接的脚本也将获得事务状态。下一个脚本很有可能(取决于您的应用程序设计)实际上不尝试提交现有事务,或者在不应该存在时将提交,而在不应该存在时回退。
这只是冰山一角。通过在每个脚本请求上进行肮脏的连接后始终尝试进行清理,可以在一定程度上缓解所有问题,但这取决于数据库,可能会很麻烦。除非您已将创建数据库连接确定为脚本中的瓶颈(这意味着您已经使用xdebug和/或xhprof完成了代码分析),否则不应将持久连接视为解决任何问题的方法。
此外,大多数现代数据库(包括PostgreSQL)都有自己喜欢的执行连接池的方式,它们没有直接基于普通PHP的持久性连接所具有的直接缺点。
为了阐明这一点,我们在工作场所使用持久连接,但不是出于选择。我们遇到了奇怪的连接行为,即从我们的应用程序服务器到数据库服务器的初始连接正好花费了三秒钟,而这本该花费的时间仅为几分之一秒。我们认为这是一个内核错误。我们放弃尝试对其进行故障排除,因为它是随机发生的并且无法按需复制,并且我们的外包IT没有具体的能力来对其进行跟踪。
无论如何,当仓库中的人员正在处理几百个进来的零件,并且每个零件要花三分半秒而不是半秒的时间时,我们必须采取行动,然后他们才绑架我们所有人,并让我们帮助他们。因此,我们在自己的ERP / CRM / CMS怪诞中花了些力气,并亲身经历了所有持久连接的恐怖。我们花了几周的时间来追踪所有看似随机发生的细微问题和奇怪行为。事实证明,我们的用户孜孜不倦地挤出应用程序的那些每周一次的致命错误正在留下锁定的表,被放弃的交易和其他不幸的不稳定状态。
这个糟糕的故事有一个意义:它以性能为名打破了我们从未料想打破的事情。 权衡是不值得的,我们热切地等待着有一天我们可以切换回普通连接而不会引起用户骚动。