数据过长导致重复插入

本该唯一的产品型号字段,在列表中大量出现重复数据,看了看代码,确实是先查库,存在就跳过,匪夷所思。

一、问题描述:

最近部署了一套新的线上环境,项目上线跑了一段时间后,发现产品型号列表中出现了大量重复的型号,代码逻辑也确实是先查库,存在就跳过,手动添加了几条做测试(之前的数据是kafka推送的),又确实不能重复添加。

二、问题排查

拿kafka的数据作对比,发现几条推送时间和数据库创建时间相同的数据,型号竟然不一样,直接按kafka推送的型号搜索也搜不到,几经排查,发现问题:当型号数据长度超出数据库对应字段长度限制时,会被截断为数据库限制的长度并存入,而不是直接报错Data too long for column,这就导致数据过长时,数据库中并没有与之完全相同的数据(都是被截断的),那么就可以重复插入,且插入的都是截取的部分。

三、问题解决

  • 通过查资料发现数据库插入数据有严格模式和非严格模式,不同模式数据处理行为不同:
数据库典型行为(严格模式)典型行为(非严格模式)
MySQL / MariaDB插入失败,报错 1406 - Data too long for column静默截断,插入字段对应长度的字符(从开头截取,并产生警告)
达梦 (DM)插入失败,报错 “字符串截断”“数据超长”静默截断
SQL ServerVARCHAR(32) 定义的是字节数,取决于编码。通常也会失败或截断。同上
  • 可以使用以下命令检查当前模式:
SELECT @@sql_mode;

如果结果中包含 STRICT_TRANS_TABLESSTRICT_ALL_TABLES,则表示严格模式已开启。

  • 于是对应的解决方案就有了:
    1. 对应的值在代码层面添加长度校验
    2. 数据库启用严格模式(按需),SET SESSION sql_mode = ‘STRICT_TRANS_TABLES,设置后字段超长插入会直接失败报错。

使用的是华为云的数据库,记得排查!!!