Ответ 1
(комментарий → ответ на запрос плаката)
Чтение в нем я вижу, что разветвленные дети наследуют их родительское соединение db, и это известная проблема: http://php.net/manual/en/function.pcntl-fork.php#70721
У меня есть цикл foreach, который вилки внутри него. После обработки вилки он обращается к базе данных. Я получаю сообщение об ошибке:
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Дело в том, что я подключаюсь к базе данных после того, как я разветкил.
Мой вопрос: зачем это происходит?
Если это произойдет, я действительно обращаюсь к базе данных перед форкированием? Будет ли дочерний узел наследовать соединения DB?
(примечание: я могу отправлять код, но он довольно велик, как и все в классах, что может быть причиной того, что я путаю, когда я обращаюсь к БД. Еще одна вещь, которую вы должны знать, это использование ZF. )
(комментарий → ответ на запрос плаката)
Чтение в нем я вижу, что разветвленные дети наследуют их родительское соединение db, и это известная проблема: http://php.net/manual/en/function.pcntl-fork.php#70721
Это помогло мне: http://www.electrictoolbox.com/mysql-connection-php-fork/
Особенно mysql_connect($server, $username, $password, true);
Кроме того, это не проблема. Это способ, которым был разработан pcntl_fork. Любое расширение (как четко указывается в документации), которое поддерживает его собственные файловые дескрипторы, будет иметь поврежденные дескрипторы, потому что все дочерние родители имеют общие дескрипторы файлов.
Вы можете избежать закрытия соединения при выходе из вильчатого процесса, если вы удалите разветвленный процесс с помощью SIGKILL.
<?php
$dbh = new PDO('pgsql:host=localhost', $username, $password);
$pid = pcntl_fork();
if($pid == 0){
register_shutdown_function(function(){
posix_kill(getmypid(), SIGKILL);
});
exit;
}
sleep(1);
$statement = $dbh->query('select 1');
var_dump($statement);
Причиной этого поведения является то, что когда PHP-процесс завершается, PHP отправляется на сервер базы данных "Завершить соединение". Но сокет будет закрыт системой только тогда, когда все ссылки на сокет будут закрыты. Использование SIGKILL помогает избежать отправки команды "Завершить соединение" на сервере базы данных.
Вам необходимо закрыть соединение MySQL в родительском процессе, а затем создать новое соединение для каждого дочернего процесса.
<?php
$dbh = new PDO('pgsql:host=localhost', $username, $password);
$pid = pcntl_fork();
if(!$pid){
// make new connection
$newConnection = new PDO('pgsql:host=localhost', $username, $password);
// do something in the child process.
exit;
}else{
// parent node
$dbh = null; // close PDO connection
}