前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GORM 并发执行 Save 更新记录报:Error 1062 (23000)

GORM 并发执行 Save 更新记录报:Error 1062 (23000)

作者头像
恋喵大鲤鱼
发布2023-10-12 16:03:56
3700
发布2023-10-12 16:03:56
举报
文章被收录于专栏:C/C++基础C/C++基础
在这里插入图片描述
在这里插入图片描述

0.前言

大咖好呀,我是恋喵大鲤鱼。

GORM(Golang Object Relational Mapping)是一个用于 Golang 的对象关系映射(ORM)库。

当需要插入或更新记录时,一般使用 Save 方法。如果只是插入,也可以使用 Create 方法。在使用 Save 方法多次更新同一条记录到 MySQL 时,却遇到了一个奇怪的问题。

1.Save 简介

先看一下 Save 方法的描述:

代码语言:javascript
复制
// 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 方法更新同一个记录会报如下错误:

代码语言:javascript
复制
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。

如果您喜欢这篇文章,欢迎关注微信公众号“恋喵大鲤鱼”了解最新精彩内容。


参考文献

GORM Duplicate primary key error returned when saving unmodified object #6171

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0.前言
  • 1.Save 简介
  • 2.问题
  • 3.原因
  • 4.小结
  • 参考文献
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档