Повторное подключение к БД после ошибки на самом деле является гораздо более сложной проблемой, чем может показаться на первый взгляд.
Моей первой идеей было написать простой класс-оболочку для PDO, который проксирует методы на внутреннем объекте PDO и сам может обрабатывать ошибки соединения:
class BetterPDO extends PDO
{
private $realPDO = NULL;
private $dsn = "";
private $username = "";
private $password = "";
private $options = [];
public function __construct ($dsn, $username = "", $password = "", $options = [])
{
$this -> dsn = $dsn;
$this -> username = $username;
$this -> password = $password;
$this -> options = $options;
}
private function getRealPDO ()
{
if (is_null ($this -> realPDO))
{
$this -> realPDO = new PDO ($this -> dsn, $this -> username, $this -> password, $this -> options);
}
return $this -> realPDO;
}
// We're only implementing exec for brevity but you have to do this for all public methods of PDO
public function exec ($sql)
{
$retries = 0;
while (true)
{
try
{
return $this -> getRealPDO () -> exec ($sql);
}
catch (PDOException $ex)
{
$this -> realPDO = NULL;
if (++$retries > 5)
{
// We've passed our retry limit
throw $ex;
}
}
}
}
}
Поскольку этот класс расширяет PDO, он можетиспользоваться везде, где может использоваться универсальный класс PDO.
Как вы можете видеть, этот подход даст вам несколько попыток, прежде чем метод exec () откажется, что позволит переподключиться после временных ошибок (это только для демонстрации и не имеет некоторых функций, которые могут потребоваться реальной реализации,как откат между попытками, адекватное ведение журнала ошибок и т. д.).Этот подход также потребует, чтобы вы проверили специфику исключения PDO на том основании, что вы не хотите, чтобы такие вещи, как синтаксические ошибки MySQL, вызывали сброс соединения и попытку повторной попытки.Вы хотите, чтобы это происходило только с такими вещами, как «Сервер ушел».
Как вы также можете видеть, реализация всех методов PDO с прокси будет непростой задачей, хотя, поскольку вам придется делать это только один раз, вероятно, стоит приложить усилия для этого.
Однако существует гораздо более серьезная проблема, которая является универсальной проблемой для любого кода, который обращается к базе данных, а не только к PDO.Что происходит, если соединение теряется в середине транзакции?Вы не хотите, чтобы ваш сценарий восстанавливал соединение и выбирал, где он остановился, в этом случае, потому что вся работа, которую вы проделали до последнего коммита, будет потеряна, и есть вероятность, что логическое возобновление не будет иметь никакого смыслапосле повторного подключения вам придется начать все сначала.Поэтому вы, вероятно, просто захотите, чтобы весь сценарий начинался заново, и попытка переподключения не имела бы никакого смысла.Вероятно, поэтому mySQLI поддерживает переподключение, а PDO - нет.
Если ваш сценарий выполняет только чтение или нетранзакционную запись, то вышеупомянутый подход все еще имеет значение, но как только вы добавляете транзакции в микс, на самом деле гораздо лучше не пытаться переподключиться.