【问题标题】:PHP automatically closing connection at the end of the scriptPHP在脚本结束时自动关闭连接
【发布时间】:2016-04-23 12:51:50
【问题描述】:

我知道 PHP 在脚本结束时会自动关闭打开的 MySQL 连接,打开持久连接的唯一可行方法是使用适当的 PHP 函数;已经提出并回答了许多问题。 我想知道的是保持临时连接而不是持久连接的好处(或不方便)

编辑: 每个 PHP 用户会话的持久连接。
例如,如下语句:

session_start();
$connection = new mysqli($host, $user, $pass, $db);
$_SESSION['connection'] = $connection;

可能会设置对 mysqli 对象的引用,该对象对同一用户在同一会话内跨网站导航执行多个查询很有用。

如果连接应该在激活后立即使用,那么让它保持打开以供进一步查询不是正确的选择吗?当多个用户从一个保持 MySQL 连接的网站请求 HTTP 页面时,这种方法可能会产生不方便的情况(以及可能的安全风险)? 我想知道更多。谢谢。

【问题讨论】:

  • 我也想知道这将如何影响性能和安全性:),赞成这个问题
  • 每个请求对于 PHP 来说都是一个新的生命周期,它没有像你在其他地方可能得到的持久状态。如果您要为多个请求/用户使用相同的连接,那么您可能会看到竞争条件(哪个查询首先完成),获取“最后插入的 id”可能会给您另一个用户插入的 id,等等
  • 无法序列化(保存 mysqli 连接)到会话,因此示例代码无法按预期工作。

标签: php mysql


【解决方案1】:

连接到 MySQL 或任何数据库都会产生开销,尽管它通常不会很大。当 MySQL 服务在不同的服务器上运行时,此开销可能会更大,或者取决于所需的身份验证方法和初始化命令。

此外,MySQL 连接可能有关联的缓存。所以重用一个连接也许能够重用这些缓存。

但是在会话中保存资源不起作用。会话数据被序列化,并存储在例如请求之间的文件。这就是为什么必须使用持久连接方法的原因。

原因是连接最终是资源,或者内部类上的套接字连接,如果不进行特殊处理,就无法“保存”。试一试,你会看到报错(使用 PDO 和 mysqli)。

mysqli::query(): Couldn't fetch mysqli

我认为没有任何方法可以在不编写扩展来实现它的情况下获得特定于会话的连接重用。不过,理论上这是可能的,理论上您可以实现一种方法,通过会话 ID 从池中拉出连接。

不过,持久数据库连接有很多潜在的缺点和风险:

  1. 如果您的应用程序创建了 TEMPORARY TABLEs,这些表在下次运行时仍然存在,因为它是同一个 MySQL 会话。

  2. 如果您设置任何变量(SET SESSION 等),它们将被保留。

  3. 根据处理事务的方式,理论上持久连接可能有正在进行的事务。

  4. 如果应用程序发出任何 LOCK 命令或使用用户锁,则锁可能会在请求之间被持有,并且在新请求中不知不觉地持有。

  5. 在多租户(共享)网络服务器上,另一个进程以某种方式获得它不应该拥有的数据库访问权限的风险更高。

  6. 这可能会使大量连接长时间处于打开状态,从而增加数据库服务器上的资源使用率。

  7. 您仍然必须预料到请求之间的连接可能会丢失。

【讨论】:

  • 另外请注意,识别一个用户并不足以知道这是否是同一会话的延续。任何持久性方法都需要为每个用户记住任何打开会话的会话 ID。如果用户启动不同的会话,您确实希望将此视为上一个会话的延续 - 它就像多线程,当您编写脚本时,您不想保留这种可能性时常记在心里。同样,如果用户启动第二个会话(可能是另一台设备),您希望将其分开。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多