使用GORM并发写入MySQL时出现报错问题咨询
基于Golang Workerpool的CSV导入MySQL并发写入问题
问题背景
用Golang实现了一个CSV导入脚本,采用Workerpool方案,多Worker处理数千个小型CSV文件,完成商品分类、打标签、品牌设置后,所有Worker写入同一张MySQL表。Worker数量≤2时运行正常,超过2个会随机崩溃,报错位于Go SQL Driver的packets.go:1102处。尝试将save()包裹在事务中未解决问题。
核心流程伪代码:
foreach (csv) { workerPool.submit(csv) } func worker(csv) { foreach (line) { import(line) } } import(line) { product = get(line) product.category = determine_category(product) product.brand = determine_brand(product) save(brand) product.tags = determine_tags(product) //and after all save(product) }
问题解答
1. MySQL是否支持向同一张表并发写入?
MySQL完全支持同一张表的并发写入,尤其是InnoDB引擎,默认用行级锁处理并发写冲突,不会因为多线程写入直接崩溃。你的问题大概率是代码层面的资源竞争、数据库连接池配置不当,而非MySQL本身不支持。
2. 若需使用事务实现并发写入,应在何处设置事务?
事务边界要贴合业务的原子性需求:
- 如果**单条商品的导入(含品牌保存+商品保存)**需要原子性,就在
import()函数开头开启事务,所有操作完成后提交,出错时回滚:func import(line) { tx, err := db.Begin() if err != nil { /* 处理错误 */ } defer func() { if r := recover(); r != nil { tx.Rollback() } }() product = get(line) product.category = determine_category(product) product.brand = determine_brand(product) saveWithTx(tx, brand) // 改用绑定事务的保存方法 product.tags = determine_tags(product) saveWithTx(tx, product) if err := tx.Commit(); err != nil { tx.Rollback() /* 处理提交错误 */ } } - 如果整个CSV文件的导入需要原子性,就在
worker()处理CSV前开启事务,全文件处理完成后再提交。 - 注意:绝对不要在Worker之间共享事务,每个Worker/每个业务原子单元必须用独立事务。
3. 报错始终发生在Go SQL Driver的packets.go:1102处,该驱动是否适合此类操作?
Go官方MySQL驱动(github.com/go-sql-driver/mysql)完全适配高并发写入场景,大量生产级系统都在使用。packets.go:1102的报错通常和以下问题相关,而非驱动本身不适用:
- 多个Worker共享了同一个
*sql.DB连接(正确做法是让每个Worker从连接池取独立连接,*sql.DB本身是并发安全的,会自动管理连接池); - 连接池配置不合理:比如
SetMaxOpenConns过小导致等待连接超时,过大超过MySQL的max_connections限制;SetConnMaxLifetime未设置,导致驱动复用了被MySQL主动关闭的过期连接; - 网络波动导致连接中断,驱动尝试复用失效连接触发报错。
4. 是否有人能提供帮助(可付费咨询数小时)?
可以提供付费技术支持,你只需要提供完整源码(重点是数据库操作、Workerpool实现、连接池配置部分),我会帮你定位并发写入的崩溃根源,修复问题并优化导入性能。
额外排查建议
- 打印完整报错堆栈,
packets.go:1102处的具体错误信息(比如invalid connection、broken pipe)是定位关键; - 检查
save()函数实现,是否存在并发修改共享变量、未正确处理数据库错误的情况; - 临时开启MySQL慢查询日志和错误日志,排查数据库层面的异常;
- 尝试将连接池
MaxOpenConns设置为和Worker数量匹配,避免连接竞争。
内容的提问来源于stack exchange,提问作者DudiDude
相关产品推荐
相关产品推荐

