You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BatchUpdateException问题:批量大小非1时触发MariaDB重复键错误

问题诊断与解决方案

问题背景

数据库迁移到Docker部署的MariaDB 10.11.4后,用继承BatchSqlUpdate的类做批量插入(批量大小100)时,带ON DUPLICATE KEY的INSERT语句触发唯一键重复错误;但把批量大小改成1就能正常执行。
依赖版本:mariadb-java-client 3.0.8、spring-jdbc 5.3.28、spring-data-jpa 2.5.7,无法升级spring-jdbc到6.x及以上。
原SQL语句存在语法错误,修正后如下:

INSERT INTO `table`(ldb, lid, scid, sid, valid)
VALUES(?, ?, (SELECT id FROM cserver WHERE ldb=? AND lid=?), ?, 1)
ON DUPLICATE KEY UPDATE 
  id=LAST_INSERT_ID(id),
  ldb=?, 
  lid=?, 
  scid=(SELECT id FROM cserver WHERE ldb=? AND lid=?), 
  sid=VALUES(sid), 
  valid=1;

注:原SQL漏写ON DUPLICATE KEY后的UPDATE关键字,且sid字段未指定赋值逻辑,这是语法硬伤。

可能的错误原因及排查方案

1. SQL语法错误导致批量执行异常

原SQL的语法错误会让数据库在批量解析时出现非预期行为,甚至把部分语句当成插入操作而非更新,直接触发唯一键冲突。先执行修正后的SQL,验证单条和批量(100)是否正常。

2. MariaDB 10.11.x批量写入与ON DUPLICATE KEY的兼容性问题

MariaDB 10.11.x对批量INSERT ... ON DUPLICATE KEY UPDATE的处理逻辑做了优化调整:

  • 批量模式下,数据库会尝试先插入所有行,再统一处理重复项,这会导致中间触发唯一键约束错误(单条执行时是逐条处理,重复就更新,不会触发冲突)
  • 解决方案:在JDBC连接URL中添加rewriteBatchedStatements=false,强制驱动逐条执行批量语句(性能会下降,但能验证是否是批量优化导致的问题)

3. mariadb-java-client 3.x与Spring JDBC 5.3.x的适配问题

mariadb-java-client 3.x对JDBC批量操作的实现和2.x差异较大,而Spring JDBC 5.3.x的BatchSqlUpdate没完全适配这种变化:

  • 尝试降级mariadb-java-client到2.7.7版本(该版本和Spring JDBC 5.3.x兼容性更好),再测试批量插入
  • 检查BatchSqlUpdate的配置:确保没开启useGeneratedKeys这类和批量插入冲突的选项,LAST_INSERT_ID(id)在批量场景下的返回逻辑和单条不一样,可能引发异常

4. Docker环境的数据库配置差异

Docker部署的MariaDB默认配置可能和原环境不同:

  • 查看数据库的sql_mode,确认是否开启了STRICT_TRANS_TABLES等严格模式,这类模式会放大批量操作的异常
  • 核对表的唯一键约束,确保Docker环境下的表结构和原环境完全一致,避免重建表时约束定义出错

验证步骤

  1. 先用修正后的SQL执行单条插入/更新,确认业务逻辑没问题
  2. 给JDBC URL加上rewriteBatchedStatements=false,保持批量100执行,看是否还报错
  3. 降级mariadb-java-client到2.7.7,重复批量测试
  4. 对比原数据库和Docker数据库的sql_mode、表约束配置

内容的提问来源于stack exchange,提问作者Szonaldo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 18:43:14