多进程共用mysql链接引发的一个问题

来源:转载

我们知道,每次fork操作系统都会复制进程的所有信息产生一个子进程(部分写时复制),其中就包括socket链接资源符。操作系统允许多个进程公用一个socket资源符,但是会有一定的风险。例如:两个进程同一时刻接收服务器发来的响应,就有可能抢读到对方的响应。

今天就遇到了与父子进程共用socket链接的一个问题,先上代码:

$mysql = mysql_connect('127.0.0.1', 'root', '123456');$process_count = 0;while(true){$pid = pcntl_fork();if($pid<0){echo "fork error" . PHP_EOL;}elseif($pid == 0){$process_count++;if($process_count > 3){pcntl_wait($status);$process_count--;}}else{$mysql = mysql_connect('127.0.0.1', 'root', '123456');// do somethingexit;}}

我们看到,子进程会重新建立mysql链接,执行完任务后退出。退出时,链接自动关闭。最开始并没有出现问题,运行了过一会,出现了mysql server has gone away的错误。而重新建立mysql链接总是返回false。

后来与人讨论,才想起mysql_connect函数的第四个参数new_link默认为flase,也就是说,在参数相同的情况下,mysql会复用没有关闭的mysql链接。

这里我们回想下,上面的程序fork第一个子进程,由于new_link参数默认为false,所以实际上是复用了父进程的mysql链接,而当这个进程退出时,链接被关闭,mysql关闭会话线程。而父进程再次创建子进程时,同样继承了mysql资源服,而父进程并不知道mysql链接已经被第一个子进程关闭,所以被fork出来的第二个子进程同样不知道mysql链接不可用(服务端已关闭)。于是mysql_connect时依然重用了之前的mysql链接,必然是链接不成功的,返回false。

问题虽然不大,但是折腾了好久,最后总算是弄清楚了原因。

写代码在于折腾。


分享给朋友:
您可能感兴趣的文章:
随机阅读: