Error 1062: Duplicate entry for unique key

TiDB版本

Server version: 5.7.25-TiDB-v4.0.7
多库

问题描述

历史库数据删除
库:yotrace
操作:
我们有一张80亿+的表,需要对历史数据进行删除,删除约50亿
使用工具:

pt-archiver --no-version-check --source xxx --charset utf8 --purge --bulk-delete --progress 1000 --txn-size 100 --limit 10000 --where="id < 6000000000"

当执行pt-archive批量删除tidb历史大表数据时,整个集群的tikv的平均负载在300%左右(每台tikv为8核心)
然后诡异的事情出现了

业务库:stat
业务侧的程序偶尔开始报 Error 1062: Duplicate entry
排查业务侧脚本和代码,并无异常,数据库也确实不存在重复的数据。

TiKV负载

出现问题的是唯一索引,该唯一索引是由三个字段组成
Duplicate entry ‘20211030-yiyun73-04892694’ for key ‘UNIQ_BKR_DLR_D’

测试复现

测试业务逻辑很简单

复现问题

批量删除1000条数据,然后在insert在这1000条数据,多次执行脚本,比如执行3次,就有一次脚本会偶尔报Error 1062: Duplicate entry

关闭删除脚本,将tikv压力降低

当我关闭pt-archive脚本时,再次批量删除1000条数据,然后在insert在这1000条数据,多次执行脚本,不在出现Error 1062: Duplicate entry

疑问?

  1. 不清楚为什么会发生这种情况,这个并没有涉及到DM同步等。查阅asktug也并没有此类问题的描述。
  2. tikv是异步提交?还是负载高,导致提交慢了,导致insert时,判断数据存在?

你可以利用 mvcc 或 snapshot 参数,看看这个值,什么时候删除,什么时候 插入的

您好,我理解您说的,我的测试很简单

代码串行依次执行删除、删除返回ok,在执行insert操作,此时insert报错

首先我不太会定位这些,即使定位底层delete后执行完成,那也就说明insert先于delete提交了。可是正常逻辑不是delete先提交的?我才提交的insert操作。难道tikv底层不是这样的逻辑?

现在的现象于我而言是insert操作先于delete提交了,触发了Error 1062: Duplicate entry

我代码就是很简单的逻辑,串行执行

_, err = db.Exec(deleteSQL)
if err != nil {
	fmt.Println(err.Error())
}

_, err = db.Exec(insertSQL)
if err != nil {
	fmt.Println(err.Error())
}

实际结果,给我的映象是insert先提交了。不知道tikv底层是异步提交还是什么机制,会不会真实发生insert先于delete提交呢。谢谢

这个看程序应该是不会的,无论是 乐观模式还是悲观模式,都是先拿 tso 的,建议你看 tidb-server 的日志(或直接开 general)