文章目录
- 1.Save 简介
- 2.问题
- 3.原因
- 4.小结
- 参考文献
1.Save 简介
先看一下 Save 方法的描述:
// Save updates value in database. If value doesn't contain a matching primary key, value is inserted.
func (db *DB) Save(value interface{}) (tx *DB)
Save 有两个作用,创建或更新。如果待保存的值不包含主键,则执行 Create,否则执行 Update(包含所有字段)。
如果是执行 Update 的话,模型字段即使是零值也会更新。这一点与 Updates 方法不同,Updates 默认只会更新非零值。
2.问题
在使用 GORM v1.24.6 时,在并发调用 Save 方法更新同一个记录会报如下错误:
Error 1062 (23000): Duplicate entry 'xxx' for key 'PRIMARY'
奇怪的是,串行调用则不会报错。
无独有偶,我发现在 GORM Github 仓库已经有人提了类似的 Issues。
Duplicate primary key error returned when saving unmodified object #6171
我在该 Issue 中也补充了我遇到的问题。
另外,我还测试了一下上一个版本 v1.24.5 没有这个问题,说明该 Bug 是版本 v1.24.6 引入的新 Bug,非历史遗留的 Bug。
3.原因
GORM 社区非常活跃,在我补充问题的当天便有人进行了回复。
从回复中可以看到,在 Issue #6171 之前,已经有人提了 PR #6149 来解决这个问题,只是还未被合入。
顺着回复的内容,找到 commit f387433,看了下提交内容。
从 commit message “Fix Save with stress tests” 和变更内容,推测 jinzhu 大佬是为了优化 Save 的更新性能,将插入前判断记录是否存在的条件去掉了,多次调用 Save 时,便出现了主键冲突的错误。
当天 Mar 23,jinzhu 大佬可能意识到了问题的存在,便将 PR #6149 合入到主干,修复了这个问题。
4.小结
如果大家遇到了同样的问题,请跳过 v1.24.6,使用之前或之后的版本,比如前一个版本 v1.24.5 或后一个版本 v1.25.0。
如果您喜欢这篇文章,欢迎关注微信公众号“恋喵大鲤鱼”了解最新精彩内容。
参考文献
Duplicate primary key error returned when saving unmodified object #6171