Hyperf 中协程批量插入 MySQL 应用 PDO 预处理+循环绑定或 QueryBuilder 的 insert() 方法,分批提交并配合事务,避免连接滥用、SQL 拼接和超长数据,确保性能与安全。

Hyperf 中用协程批量插入 MySQL,核心是用 PDO::prepare 预处理 + foreach 绑定参数,配合协程安全的连接复用,避免“每条 insert 单独执行”带来的性能瓶颈。
用 PDOStatement 批量绑定执行
Hyperf 默认使用 Swoole\Coroutine\MySQL 或 PDO 作为数据库驱动。推荐用 PDO(更稳定、支持预处理),且确保配置中启用了协程化(enable_coroutine => true)。
关键点:
- 单次 prepare,多次 execute,减少 SQL 解析开销
- 用
bindValue或bindParam绑定每行数据,避免拼接 SQL - 所有操作在同一个协程内完成,连接自动复用,无需手动管理
示例代码:
$pdo = $this->container->get(PDO::class);
$stmt = $pdo->prepare("INSERT INTO user (name, age, email) VALUES (?, ?, ?)");
foreach ($users as $user) {
$stmt->bindValue(1, $user['name'], PDO::PARAM_STR);
$stmt->bindValue(2, $user['age'], PDO::PARAM_INT);
$stmt->bindValue(3, $user['email'], PDO::PARAM_STR);
$stmt->execute();
}
用 QueryBuilder 批量插入(更简洁)
Hyperf 的 Db 组件(基于 Hyperf\Database)支持原生批量插入语法:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 调用
insert()传入二维数组,底层自动生成INSERT ... VALUES (),(),() - 单次查询完成,效率比循环 execute 更高
- 注意单次插入行数不宜过多(建议 ≤ 1000 行),防止 SQL 过长或超 max_allowed_packet
示例:
$data = [
['name' => 'Alice', 'age' => 25, 'email' => 'a@x.com'],
['name' => 'Bob', 'age' => 30, 'email' => 'b@x.com'],
];
$result = $this->db->table('user')->insert($data);
大数量分批提交防内存/超时
插入几万行时,不能一次性全塞进去。需手动切块,每批 500–1000 行,用事务包裹提升速度并保证原子性:
- 用
beginTransaction()→ 批量 insert →commit() - 捕获异常时
rollback() - 每批执行完可
gc_collect_cycles()(可选),缓解协程内存累积
示例逻辑:
$chunkSize = 500;
foreach (array_chunk($allUsers, $chunkSize) as $chunk) {
$this->db->transaction(function () use ($chunk) {
$this->db->table('user')->insert($chunk);
});
}
避坑提醒
常见问题和对应做法:
-
不要在循环里 new PDO 或反复 getConnection:Hyperf 的 Db 连接池已协程安全,直接用注入的
Db或PDO实例即可 - 避免用字符串拼接 SQL 插入:易 SQL 注入,且无法利用预处理缓存
-
时间字段别传字符串:如
created_at建议用date('Y-m-d H:i:s')或 Carbon::now()->toDateTimeString() -
自增 ID 需要返回?:批量插入不支持返回多 ID,如需,改用循环 +
lastInsertId()(性能略低)或改用 REPLACE/INSERT ... ON DUPLICATE KEY UPDATE
不复杂但容易忽略。










