这在 mysqlnd 中不起作用,并且被标记为 wontfix:https://bugs.php.net/bug.php?id=52561
(PHP 5, PHP 7, PHP 8)
mysqli::ping -- mysqli_ping — 对服务器连接进行 ping 操作,或在连接断开时尝试重新连接
面向对象风格
过程式风格
检查与服务器的连接是否正常。如果连接已断开,并且启用了全局选项 mysqli.reconnect,则会尝试自动重新连接。
注意: mysqlnd 驱动程序会忽略 php.ini 设置 mysqli.reconnect,因此永远不会尝试自动重新连接。
此函数可供长时间处于空闲状态的客户端使用,用于检查服务器是否已关闭连接,并在必要时重新连接。
如果启用了 mysqli 错误报告 (MYSQLI_REPORT_ERROR
) 并且请求的操作失败,则会生成警告。此外,如果模式设置为 MYSQLI_REPORT_STRICT
,则会抛出 mysqli_sql_exception 而不是警告。
示例 #1 mysqli::ping() 示例
面向对象风格
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* 检查连接 */
if ($mysqli->connect_errno) {
printf("连接失败: %s\n", $mysqli->connect_error);
exit();
}
/* 检查服务器是否存活 */
if ($mysqli->ping()) {
printf ("我们的连接正常!\n");
} else {
printf ("错误: %s\n", $mysqli->error);
}
/* 关闭连接 */
$mysqli->close();
?>
过程式风格
<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");
/* 检查连接 */
if (mysqli_connect_errno()) {
printf("连接失败: %s\n", mysqli_connect_error());
exit();
}
/* 检查服务器是否存活 */
if (mysqli_ping($link)) {
printf ("我们的连接正常!\n");
} else {
printf ("错误: %s\n", mysqli_error($link));
}
/* 关闭连接 */
mysqli_close($link);
?>
上面的示例将输出
Our connection is ok!
这在 mysqlnd 中不起作用,并且被标记为 wontfix:https://bugs.php.net/bug.php?id=52561
正如 jay at grooveshark dot com 很乐意地指出的那样,mysqlnd 驱动程序(正在变得非常标准)不遵守重新连接命令。如果您有一个数据库包装器类(希望您有),您可以实现自己的 ping() 版本,例如
<?php
class db extends mysqli
{
private $db_host;
private $db_user;
private $db_pass;
private $db_name;
private $persistent;
public function __construct($db_host, $db_user, $db_pass, $db_name, $persistent = true)
{
$this->db_host = $db_host;
$this->db_user = $db_user;
$this->db_pass = $db_pass;
$this->db_name = $db_name;
$this->persistent = $persistent;
parent::init();
parent::options(MYSQLI_OPT_CONNECT_TIMEOUT, 1);
@parent::real_connect(($this->persistent ? 'p:' : '') . $this->db_host, $this->db_user, $this->db_pass, $this->db_name);
if ($this->connect_errno)
die("所有数据库服务器都已关闭!\n");
}
public function ping()
{
@parent::query('SELECT LAST_INSERT_ID()');
if ($this->errno == 2006)
$this->__construct($this->db_host, $this->db_user, $this->db_pass, $this->db_name, $this->persistent);
}
...
}
$db = new db(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// 一些可能需要很长时间执行的代码放在这里
// 为安全起见,尝试优雅地重新连接
$db->ping();
// 现在我们应该能够再次运行查询
$db->query('SELECT LAST_INSERT_ID()');
?>
如果您愿意,您甚至可以在 db::query() 的顶部添加 "$this->ping();" 来避免任何显式的重新连接调用,但我并不推荐这样做,因为每次在运行您的真实目标查询之前运行便宜的 "SELECT LAST_INSERT_ID()" 查询会带来 (轻微) 的开销。可能还有比 "SELECT LAST_INSERT_ID()" 更便宜的查询可以运行,但它是我想到的第一个,而且对于大多数目的来说已经足够便宜了,因为您不应该经常调用 ping()。
关于 mysqli.reconnect 选项的行为在 Debian PHP 包中默认设置为 Off。所以我建议更新第一行描述,关于在 mysqli.reconnect 选项上的建议。 (实践笔记 ;))