在PDO中使用持久连接的缺点是什么

2022-08-30 06:28:49

在 PDO 中,可以使用该属性使连接持久化。根据 php 手册 -PDO::ATTR_PERSISTENT

持久性连接不会在脚本结束时关闭,但当另一个脚本使用相同的凭据请求连接时,将缓存并重新使用持久连接。通过持久连接缓存,您可以避免每次脚本需要与数据库通信时建立新连接的开销,从而加快 Web 应用程序的速度。

本手册还建议在使用 PDO ODBC 驱动程序时不要使用持久连接,因为它可能会妨碍 ODBC 连接池进程。

因此,显然在PDO中使用持久连接似乎没有缺点,除了最后一种情况。但是,我想知道使用此机制是否有任何其他缺点,即此机制导致性能下降或类似情况的情况。


答案 1

请务必阅读下面的答案,其中详细介绍了缓解此处概述的问题的方法。


使用PDO存在与执行持久连接的任何其他PHP数据库接口相同的缺点:如果您的脚本在数据库操作过程中意外终止,则获得剩余连接的下一个请求将从死脚本中断的位置继续。连接在进程管理器级别保持打开状态(Apache表示mod_php,如果您使用的是FastCGI,则为当前的FastCGI进程等),而不是PHP级别,并且PHP不会告诉父进程在脚本异常终止时让连接死亡。

如果失效脚本锁定了表,则这些表将保持锁定状态,直到连接终止或获取连接的下一个脚本解锁表本身。

如果死脚本处于事务的中间,则可能会阻塞大量表,直到死锁计时器启动,即使这样,死锁计时器也可以杀死较新的请求,而不是导致问题的旧请求。

如果死脚本位于事务的中间,则获取该连接的下一个脚本也会获取事务状态。很有可能(取决于您的应用程序设计)下一个脚本实际上可能从未尝试提交现有事务,或者在不应该提交时提交,或者在不应该提交时回滚。

这只是冰山一角。通过在每个脚本请求的脏连接之后始终尝试清理,可以在一定程度上缓解这一切,但根据数据库的不同,这可能是一种痛苦。除非您已将创建数据库连接确定为脚本中的瓶颈(这意味着您已使用 xdebug 和/或 xhprof 进行了代码分析),否则不应将持久连接视为任何操作的解决方案。

此外,大多数现代数据库(包括PostgreSQL)都有自己喜欢的执行连接池的方式,这些方式没有基于普通PHP的持久连接那样的直接缺点。


为了澄清一点,我们在我的工作场所使用持久的联系,但不是自愿的。我们遇到了奇怪的连接行为,从我们的应用程序服务器到数据库服务器的初始连接正好需要三秒钟,而它应该只需要几分之一秒。我们认为这是一个内核错误。我们放弃了尝试对它进行故障排除,因为它是随机发生的,无法按需复制,而且我们的外包IT没有具体的能力来跟踪它。

无论如何,当仓库里的人正在处理几百个进货零件时,每个零件需要三秒半而不是半秒,我们不得不在他们绑架我们所有人并让我们帮助他们之前采取行动。因此,我们在我们本土的ERP / CRM / CMS怪物中翻转了一些东西,并亲身体验了持久连接的所有恐怖。我们花了数周时间才追踪到所有看似随机发生的微妙小问题和奇怪的行为。事实证明,我们的用户每周一次的致命错误会从我们的应用程序中挤出来,这些错误会留下锁定的表格,废弃的交易和其他不幸的不稳定状态。

这个可泣的故事有一个观点:它打破了我们从未预料到会打破的东西,所有这些都是以表演的名义。这种权衡是不值得的,我们急切地等待着有一天我们可以切换回正常连接,而不会受到用户的骚乱。


答案 2

针对查尔斯的上述问题,

来自 : http://www.php.net/manual/en/mysqli.quickstart.connections.php -

关于持久连接的一个常见抱怨是,在重用之前,它们的状态不会重置。例如,未结和未完成的事务不会自动回滚。但是,在将连接放入池和重用它之间发生的授权更改也不会得到反映。这可能被视为不必要的副作用。相反,“持久”这个名字可以被理解为国家持久的承诺。

mysqli扩展支持持久连接的两种解释:状态持久化和重用前的状态重置。默认值为重置。在重用持久连接之前,mysqli 扩展会隐式调用以重置状态。持久连接对用户显示为刚刚打开一样。以前使用的任何伪影都不可见。mysqli_change_user()

该函数是一项成本高昂的操作。为了获得最佳性能,用户可能希望使用设置的编译标志重新编译扩展。mysqli_change_user()MYSQLI_NO_CHANGE_USER_ON_PCONNECT

用户可以在安全行为和最佳性能之间进行选择。两者都是有效的优化目标。为了便于使用,安全行为已成为默认行为,但以牺牲最佳性能为代价。


推荐