记一次 Gorm 批量插入遇到的问题以及解决方案

Posted CG国斌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次 Gorm 批量插入遇到的问题以及解决方案相关的知识,希望对你有一定的参考价值。

问题现象

最初,我们用的是老版本的 Gorm,但是因为老版本不支持批量插入的功能,所以我们将 Gorm 做了升级,升级到1.21.9版本。

  • https://github.com/go-gorm/gorm/releases/tag/v1.21.9

升级之后,Gorm 确实支持了批量插入的功能。但因为我们后续用到了批量插入返回的记录ID,也就是数据库自增生成的主键 ID 这个值,这时就出现了问题。当然,出现这个问题是有一个前提的,那就是数据库设置的自增步长大于 1,如果自增步长是 1,则没有问题。

因为数据库主从的问题,我们设置的数据库自增步长是 2,所以我们遇到了这个问题。问题的现象是,我们批量插入了三条记录,数据库自增生成的 ID 分别是 1074、1076 和 1078,但 Gorm 返回的结果中,记录的 ID 分别是 1074、1075 和 1076,这意味着 Gorm 返回的 ID 和数据库自增生成的 ID 不一致

为了验证这个问题,大家可以通过下面的两条 SQL 查看数据库的自增属性和设置自增步长。

  • 查看自增属性:show variables like '%increment%';
  • 设置自增步长:set @@auto_increment_increment=1;

需要注意的是,上述设置步长命令仅对单次链接有效,重启 mysql 后失效。

解决方案

在出现问题之前,我们用于接收数据库记录的结构为:

type Record struct {
	ID         int64     `gorm:"primary_key;column:id;type:bigint(20) unsigned;not null" json:"id"`       
	...
	...                   
	CreateTime time.Time `gorm:"column:create_time;type:timestamp;not null" json:"create_time"`
}

在出现问题之后,为了解决这个问题,我们用于接收数据库记录的结构修改为:

type Record struct {
	ID         int64     `gorm:"primary_key;column:id;type:bigint(20) unsigned;not null;autoIncrementIncrement:2" json:"id"`       
	...
	...                   
	CreateTime time.Time `gorm:"column:create_time;type:timestamp;not null" json:"create_time"`
}

两者的差异就在于后者 ID 的gorm配置之中,新增了autoIncrementIncrement:2标签。其中,

  • autoIncrementIncrement:表示自动步长,控制连续记录之间的间隔;
  • 2:表示我们数据库设置的自增步长。

实际上,应该是autoIncrementIncrement:N,其中N对应我们数据库设置的自增步长,因为我们数据库的自增步长设置是 2,所以这里就配置成了 2,具体可以根据实际情况进行调整。

最后,给大家推荐「Gorm 文档」,没事多看看,可以避免采坑啊!

以上是关于记一次 Gorm 批量插入遇到的问题以及解决方案的主要内容,如果未能解决你的问题,请参考以下文章

记一次 Gorm 批量插入遇到的问题以及解决方案

记一次开发过程中,iview遇到的一些坑以及解决办法

记一次通过nginx反代网站请求总是超时的问题

JVM记一次PermGen space内存溢出实战案例

记一次OOM查询处理过程

记一次 Hibernate 插入数据中文乱码报错解决