【发布时间】:2022-08-16 09:11:19
【问题描述】:
我正在尝试使用Gorm、Golang 和 MySQL 批量插入许多记录。我的代码如下所示:
package main
import (
\"fmt\"
\"sync\"
\"gorm.io/driver/mysql\"
\"gorm.io/gorm\"
)
type Article struct {
gorm.Model
Code string `gorm:\"size:255;uniqueIndex\"`
}
func main() {
db, err := gorm.Open(mysql.Open(\"root@tcp(127.0.0.1:3306)/q_test\"), nil)
if err != nil {
panic(err)
}
db.AutoMigrate(&Article{})
// err = db.Exec(\"TRUNCATE articles\").Error
err = db.Exec(\"DELETE FROM articles\").Error
if err != nil {
panic(err)
}
// Build some articles
n := 10000
var articles []Article
for i := 0; i < n; i++ {
article := Article{Code: fmt.Sprintf(\"code_%d\", i)}
articles = append(articles, article)
}
// // Save articles
// err = db.Create(&articles).Error
// if err != nil {
// panic(err)
// }
// Save articles with goroutines
chunkSize := 100
var wg sync.WaitGroup
wg.Add(n / chunkSize)
for i := 0; i < n; i += chunkSize {
go func(i int) {
defer wg.Done()
chunk := articles[i:(i + chunkSize)]
err := db.Create(&chunk).Error
if err != nil {
panic(err)
}
}(i)
}
wg.Wait()
}
当我运行这段代码有时(大约三分之一)我得到这个错误:
panic: Error 1213: Deadlock found when trying to get lock; try restarting transaction
如果我在没有 goroutines(注释行)的情况下运行代码,我不会遇到死锁。另外,我注意到如果我删除 code 字段上的唯一索引,死锁就不会再发生了。如果我用TRUNCATE articles 替换DELETE FROM articles 语句,死锁似乎不再发生。
我也用 Postgresql 运行了相同的代码,它可以工作,没有死锁。
知道为什么死锁只发生在 MySQL 上的唯一索引以及如何避免它?
-
这可能会有所帮助。 stackoverflow.com/a/32502736/7409103
标签: mysql go deadlock bulkinsert go-gorm