【发布时间】:2016-02-11 13:55:43
【问题描述】:
问题
我们告诉 PDO 将每个问题包装到异常中。 在某些情况下,它会生成一些警告,然后才会引发异常。
为什么会这样做?
重复?
关于 SO 没有关于它的正确答案。最后一个问题是PHP PDO Exception + Warning on MySQL Has Gone Away?,但人们只是将其标记为重复,而不是仔细回答。
接受的答案不能回答为什么这样做以及何时这样做。所以我研究并会回答。
【问题讨论】:
问题
我们告诉 PDO 将每个问题包装到异常中。 在某些情况下,它会生成一些警告,然后才会引发异常。
为什么会这样做?
重复?
关于 SO 没有关于它的正确答案。最后一个问题是PHP PDO Exception + Warning on MySQL Has Gone Away?,但人们只是将其标记为重复,而不是仔细回答。
接受的答案不能回答为什么这样做以及何时这样做。所以我研究并会回答。
【问题讨论】:
这是因为 PDO 可以使用 mysqlnd 驱动程序,它不遵守任何 PDO 的“convert-issues-to-extensions”策略。
我们清楚地看到直接调用php_error_docref。
其中一个示例,显示在previous question,由以下几行解释:https://github.com/php/php-src/blob/PHP-5.5.31/ext/mysqlnd/mysqlnd_wireprotocol.c#L35:L61
【讨论】:
使用 set_error_handler() 和 restore_error_handler()
public function query($sql)
{
$retries = 0;
$result = null;
while (true) {
try {
set_error_handler(function () {
});
$result = $this->pdo->query($sql);
restore_error_handler();
break;
} catch (Exception $e) {
restore_error_handler();
if (++$retries < self::RECONNECT_ATTEMPT) {
if (strpos($e->getMessage(), 'server has gone away') !== false) {
$this->connect();
$this->getLogger()->info('Reconnect database, reason: server has gone away');
}
} else {
throw $e;
}
}
}
return $result;
}
【讨论】: