使用GORM并发写入MySQL会导致错误

z6psavjg  于 2023-01-28  发布在  Go
关注(0)|答案(1)|浏览(342)

我已经在Golang实现了一个复杂的csv导入脚本。我使用了Workerpool实现。在这个Workerpool中,工作人员会运行上千个小csv文件,对产品进行分类、标记和品牌化。他们都写入同一个数据库表。到目前为止一切顺利。
我所面临的问题是,如果我选择了2个以上的工人,进程崩溃,并随机显示以下消息

工作流程为

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)
}

我尝试将保存()调用 Package 在事务中,但没有用。
现在我有以下问题:

  1. MySQL适合并发保存到1个表吗?
    1.如果需要事务来完成此操作,则应将其设置在何处?
  2. Go SQL驱动程序(错误总是发生在packets.go:1102中)适合这样做吗?
    1.有人能帮我吗(也许雇几个小时)?
    我完全卡住了。如果有帮助的话,我也可以分享源代码。但是我首先想知道你猜这是我的代码还是一个普遍的问题。
nwnhqdif

nwnhqdif1#

在每个goroutine(或者线程,对于使用线程的语言)中打开一个新的数据库连接。
MySQL的协议是有状态的,这意味着如果多个goroutine试图使用同一个连接,请求和响应会变得非常混乱。
在goroutine之间共享任何其他类型的有状态协议连接时,你也会遇到同样的问题。
例如,ftp也是一个有状态的协议,这可能更容易理解,一个客户端goroutine可能会发送一个类似“get file x”的消息,而响应应该是一系列包含该文件内容的消息,如果另一个goroutine试图使用同一个连接,而这个请求/响应正在进行中,第二个goroutine会读取它没有请求的文件的数据包,而第一个请求该文件的goroutine会发现它所期望的数据包已经被读取了。
类似地,MySQL的协议不支持多个客户端goroutine共享一个连接。

相关问题