php 多进程使用一个数据库连接插入数据出错怎么解决??
代码:
// 一个数据库连接
// 供应近百个进程并行使用
// 结果导致,只有第一个创建的进程插入了数据
// 后面的进程全部无法插入数据到数据库
// 提示 MySQL server has gone away
$con = new PDO('mysql:host=127.0.0.1;dbname=Process' , 'root' , '364793');
$num = 50 * 10000; // 插入的数量
$tb_name = 'test_tb';
$sex_range = array("男" , "女" , "两性" , "未知" , "male" , "female" , "both" , "unknow");
$sex_range_count = count($sex_range);
$unit_num = 5000; // 单次插入数量
$p_list = array();
$p_num = ceil($num / $unit_num);
$is_main_process = true;
$file = '/home/cxl/桌面/insert.log';
// 清空插入日志(以便重新计算插入耗费时间)
$fs = fopen($file , 'w');
fwrite($fs , '');
fclose($fs);
for ($n = 1; $n <= $p_num; ++$n)
{
$min = ($n - 1) * $unit_num;
$max = min($min + $unit_num , $num);
// echo 'per insert number: min->' . $min . ' ; max->' . $max . PHP_EOL;
$p = pcntl_fork();
if ($p === -1) {
exit('create process ' . $n . ' failed!' . PHP_EOL);
} else if ($p === 0) {
$is_main_process = false;
$sql = 'insert into ' . $tb_name . ' (name , sex , height) values ';
for ($i = $min; $i < $max; ++$i)
{
// name
$name = join('' , random(10 , 'mixed'));
// sex
shuffle($sex_range);
$sex = $sex_range[rand(0 , $sex_range_count - 1)];
// height
$height = rand(50 , 175);
$sql .= '("' . $name . '" , "' . $sex . '" , ' . $height . ') ,';
}
$sql = mb_substr($sql , 0 , -1);
// 每批次插入开始时间
$s_time = microtime(true);
if (!$con->query($sql)) {
exit('插入批次:' . $n . ' 失败' . PHP_EOL);
}
// 每批次插入结束时间
$e_time = microtime(true);
// 每批次插入耗费的时间
$duration = $e_time - $s_time;
// 输出信息
echo '插入批次 ' . $n . ' 花费时间: ' . $duration . 's' . PHP_EOL;
// 记录每次插入耗时(用于统计总耗时)
$fs = fopen($file , 'a');
fwrite($fs , $duration . "\r\n");
fclose($fs);
break;
} else {
$p_list[] = $p;
}
}
结果:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
貌似是子进程1结束的时候,所有的资源都释放了,而其中的pdo对象时复制的父进程的,文件描述符是同一个,然后也就被关闭了,其它进程执行的时候自然就会出现mysql连接断开了。
另外,不要多个进程共用一个mysql连接,如果共用1个连接,那么返回的结果无法保证被哪个进程处理。持有连接的进程理论上都可以对这个连接进行读写,这样数据就发生错乱了。
参考:是否可以共用1个redis或mysql连接,对pcntl同样有效
使用
$con = new PDO('mysql:host=127.0.0.1;dbname=Process' , 'root' , '364793',array(PDO::ATTR_PERSISTENT => true));
添加第四个参数在一个进程的生命周期中建立一个长连接
嗯,我也遇到这个问题,本质是fork之后父子进程共享了同一个socket,TLPI这本书里提到了fork之后链接的表现。可以看一下我的总结,一起交流一下:https://www.cnblogs.com/zhaoyixing/p/10847300.html