php 多进程使用一个数据库连接插入数据出错怎么解决??

发布于 2022-09-04 10:30:11 字数 2472 浏览 24 评论 0

代码:

// 一个数据库连接
// 供应近百个进程并行使用
// 结果导致,只有第一个创建的进程插入了数据
// 后面的进程全部无法插入数据到数据库
// 提示 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞旧 2022-09-11 10:30:11

貌似是子进程1结束的时候,所有的资源都释放了,而其中的pdo对象时复制的父进程的,文件描述符是同一个,然后也就被关闭了,其它进程执行的时候自然就会出现mysql连接断开了。

另外,不要多个进程共用一个mysql连接,如果共用1个连接,那么返回的结果无法保证被哪个进程处理。持有连接的进程理论上都可以对这个连接进行读写,这样数据就发生错乱了。

参考:是否可以共用1个redis或mysql连接,对pcntl同样有效

秉烛思 2022-09-11 10:30:11

使用
$con = new PDO('mysql:host=127.0.0.1;dbname=Process' , 'root' , '364793',array(PDO::ATTR_PERSISTENT => true));
添加第四个参数在一个进程的生命周期中建立一个长连接

相思碎 2022-09-11 10:30:11

嗯,我也遇到这个问题,本质是fork之后父子进程共享了同一个socket,TLPI这本书里提到了fork之后链接的表现。可以看一下我的总结,一起交流一下:https://www.cnblogs.com/zhaoyixing/p/10847300.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文