insert into on duplicate key update - 返回主键问题

本文探讨了在使用 Mybatis 的 Insert on Duplicate Key Update 操作时,遇到的主键问题。当更新数据时,Mybatis 会错误地回填内存中的主键值,导致与数据库中的实际主键不符。解决方案是通过反查数据库获取正确的主键,以避免内存中的主键信息被错误修改。该问题仅影响内存中的 PO 对象,不会影响 MySQL 数据库本身。
摘要由CSDN通过智能技术生成

问题 - InsertOrUpdate 会修改内存主键

在项目中,需要批量插入销售记录数据进入 record 表。这张表有自己的唯一键 sale_no 作为唯一标识号。我们需要同步 Mysql 表与 ES 索引,设计成同时双写 mysql 和 es。代码如下

双写逻辑

SQL

insert into record
(column1, column2, ...)
values
(value1, value2, ...)
...
on duplicate key update
column1 = values(values1)
...
private void saveRecords(List<RecordPO> RecordPOList) {
   
	// 1. 这里使用 insert into on duplicate key update SQL 语句批量插入
	markableRecordPOUdfMapper.batchInsertReplace(markableRecordPOList);
	// 2. 批量更新 ES,转成 ES 类型 PO 再 Bulk
	RecordSearch.bulkIndex(RecordIndexConverter.toIndexObjects(markableRecordPOByUniqueSerialNo));
	// ......
    }

可是出现一个奇怪的现象,每次更新数据表后,es 都会比 mysql 多几个数据。

测试验证

最后排查结果是:batchInsertReplace 方法返回的主键是有问题的,不是真实数据库存储的主键,而是 Mybatis 自己生成的。下面是实验和问题详解。

测试验证

自己造出实验数据,一遍insert一边update,我们预期的是 insert 的PO 赋值出插入数据库的自增主键,update 的 PO 赋值更新的主键。

结果出人意料,插入数据的PO获得主键 115066,UPDATE 的 PO 获得主键居然是 115067(数据库里真实的主键应该是113242,所以只能更新那条记录,却根本没获取到要更新记录的主键)。

所以这个 PO 回填的主键是假的,只是 Mybatis 自增主键 + 1

解决方案

强制走从库反查数据库再读取一遍主键

  1. 为什么要反查,因为批量插入的健只有在mysql中才能获取到
  2. 为什么强制走从库?因为刚插入新数据,会有主从延迟
markableRecordPOUdfMapper.batchInsertReplace(markableRecordPOList);
// 用唯一索引强制走从库读取
List<MarkableRecordPO> markableRecordPOByUniqueSerialNo = getRecordPOBySaleSerialNoFromMaster(uniqueSerialNoList);
RecordSearch.bulkIndex(RecordIndexConverter.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值