php 使用多进程批量插入数据

多进程使用场景

多进程一般用来处理消息队列,等数据量比大的任务。

使用限制

php多进程需要pcntlposix扩展支持。可以使用php -m查看是否安装该扩展。
需要注意的是CLI模式和CGI模式时用的php.ini并非同一个配置,需要单独配置。一般情况下使用默认配置即可
php多进程只能运行在CLI环境下,在web服务器环境下会出现无法预期的结果,要慎用!
子进程的个数最好和服务器的核数匹配,子进程超过cpu核数就会存在执行分配问题,所以不建议子进程开得很多。

核心函数

pcntl_fork
创建子进程,一次调用两次返回。在父进程中返回子进程id,在子进程中返回0,创建子进程失败返回-1。所以可以根据返回值判断当前是处于子进程或父进程。
pcntl_waitpid
等待或返回fork的子进程状态,具体参数可以参考文档

扩展知识

僵尸进程:当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。
孤儿进程:是指其父进程执行完成或被终止后仍继续运行的一类进程。这些孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
守护进程:在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。

php版本 注:要有pcntl扩展(php -m查询是否有此扩展)

 

mysql 数据库(test1) 数据表

CREATE TABLE `test1` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '',
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=90001 DEFAULT CHARSET=utf8mb4;

具体代码:

<?php

class TestController { private $pid_num = 5;//进程数 /** * 等待进程结束 */ public function wait() { //等待子进程结束 while (pcntl_waitpid(0, $status) != -1) { echo "子进程结束了" . PHP_EOL; } } /** * 插入数据 * @param $fpid * @param $cpid */ public function runSql($fpid, $cpid) { $link = mysqli_connect('127.0.0.1:3306', 'root', '123456', 'test'); for ($j = 0; $j < 2000; $j++) { $time = date('Y-m-d H:i:s', time()); $sqlTpl = 'INSERT INTO `%s` (`name`,`create_time`) VALUES ("%s", "%s")'; $name = "fpid:{$fpid},cpid:{$cpid},j:{$j}"; $table = 'test1'; $sql = sprintf($sqlTpl, $table, $name, $time); mysqli_query($link, $sql); } mysqli_close($link); } /** * 拆分为5个进程,每个进程处理2000条插入 */ public function actionTest() { if (!function_exists("pcntl_fork")) { die("pcntl extention is must !"); } declare (ticks=1); $start_time = date('Y-m-d H:i:s', time()); for ($i = 0; $i < $this->pid_num; $i++) { $pid = pcntl_fork(); //创建一个子进程 if ($pid > 0) { //主进程代码 //父进程获取自己的进程id $fpid = posix_getpid(); // echo "父进程--" . $fpid . PHP_EOL; cli_set_process_title("我是父进程,我的进程id是{$fpid}."); // sleep(5); } else if ($pid == 0) { //子进程代码 //子进程获取自己的进程id $cpid = posix_getpid(); //获取当前进程id $fpid = posix_getppid(); //获取父进程id echo "父进程--{$fpid}子进程--" . $cpid . PHP_EOL; cli_set_process_title("我是{$fpid}的子进程,我的进程id是{$cpid}."); $this->runSql($fpid, $cpid); // sleep(2); exit(0); //子进程执行完自己的任务后,退出 } else { //创建失败 echo "创建子进程失败", PHP_EOL; break; } } $this->wait(); //所有子进程结束 echo "父进程结束" . PHP_EOL; $end_time = date('Y-m-d H:i:s', time()); echo "开始时间{$start_time},结束时间{$end_time}" . PHP_EOL; } }
原文地址:https://www.cnblogs.com/-mrl/p/15014574.html