MySQL pcntl_fork和MySQL连接失效的问题
阅读更多:MySQL 教程
背景
在使用MySQL和php开发Web应用或者后台任务时,可能会遇到pcntl_fork和MySQL连接失效的问题。pcntl_fork是创建子进程的系统调用,而MySQL连接是被父进程持有的,子进程无法继承父进程的MySQL连接句柄,所以子进程需要重新连接一次MySQL。但是,如果子进程不连接或者连接超时则会导致MySQL连接失效,从而出现各种问题。
场景
在Web应用或后台任务中,经常会使用pcntl_fork和MySQL,下面是两个场景:
- 多进程处理任务,例如异步处理MQ消息
- 多进程并发执行Web请求,例如使用swoole_http_server
这两个场景都会要求创建多个子进程,而所有子进程都需要操作MySQL,通常这些子进程是独立的,它们需要重新连接MySQL,并且每个子进程应该有自己的MySQL连接,而不是共享父进程的连接。
问题
在使用pcntl_fork创建子进程时,如果子进程不重新连接时,就会导致MySQL连接失效。
解决方案
为了解决MySQL pcntl_fork问题,我们需要保证以下几点:
- 子进程需要重新连接MySQL,并且连接必须在pcntl_fork之前建立。
- 子进程需要维护自己的MySQL连接,不能共享父进程的连接。
- 在创建MySQL连接时,需要设置reconnect选项,并且设置超时时间。
为了达到以上的要求,我们需要对MySQL连接的代码进行改造。
示例代码
<?php
class Foo {
private pdo;
privateconfig = [
'dsn' => 'mysql:host=127.0.0.1;dbname=test',
'username' => 'root',
'password' => '123456',
'charset' => 'utf8mb4',
];
function __construct() {
this->pdo = new PDO(this->config['dsn'], this->config['username'],this->config['password']);
this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);this->pdo->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8mb4');
this->pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);this->pdo->setAttribute(PDO::ATTR_TIMEOUT, 10);
this->pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, true);this->pdo->setAttribute(PDO::ATTR_PERSISTENT, false);
this->pdo->setAttribute(PDO::MYSQL_ATTR_RECONNECT, true);
}
function getConn() {
returnthis->pdo;
}
function __destruct() {
this->pdo = null;
}
}foo = new Foo();
pdo =foo->getConn();
pid = pcntl_fork();
if (pid == -1) {
// error
} else if (pid == 0) {
// child processfoo = new Foo();
pdo =foo->getConn();
// do some other things
} else {
// parent process
pcntl_waitpid(pid,status);
}
?>
在上面的示例代码中,我们创建了一个PDO对MySQL进行连接,并且对其设置了reconnect选项和超时时间。在pcntl_fork之前创建了一个连接,然后在子进程中重新创建了一个连接。
总结
MySQL pcntl_fork问题很常见,但是我们可以通过正确的技术手段来解决它。我们可以在pcntl_fork之前,创建MySQL连接。这样,我们就可以保证每个子进程都有自己的MySQL连接,并且连接始终可用。在创建连接时,我们需要注意一些必要的设置,例如reconnect选项以及超时时间等。通过这些处理,我们可以避免MySQL连接失效带来的各种问题,确保Web应用和后台任务的正常运行。