【 TiDB 使用环境】生产环境
【 TiDB 版本】v4.0.8
【遇到的问题】
问题背景
1.显示开启2个事务
2.insert语句使用on duplicate key update
3.事务1与事务2未提交的情况下写入uk相同的一行数据
4.事务1提交后事务2提交
5.预期:事务2的last_insert_id()位上一次写入的主键id值
【问题现象及影响】
事务1 | 事务2 |
---|---|
start transaction; | |
start transaction; | |
select last_insert_id(); //27 | |
select last_insert_id(); //28 | |
insert into test1_byxx(name,uid,mtime) values (‘aa’,11,now()) on duplicate key update name=‘aa’,uid=11,mtime=now(); //Query OK, 1 row affected | |
select last_insert_id(); //31 | |
insert into test1_byxx(name,uid,mtime) values (‘aa’,11,now()) on duplicate key update name=‘aa’,uid=11,mtime=now(); //阻塞 | |
commit; | //Query OK, 2 rows affected |
select last_insert_id(); //32 | |
commit; |
解读:
1.事务1上次写入的主键id为27,事务2上次写入的主键id为28
2.uid为唯一索引,事务1和事务2写入uid相同的一行数据
3.事务1先提交,事务2后提交,事务1的last_insert_id()为31(本次写入的数据行主键id值)符合预期,事务2不符合预期,返回的last_insert_id()为32,应当返回28
影响:
业务依赖last_insert_id()往关联表写入数据,事务2返回的id主表中并不存在,导致关联表中写入了一条脏数据
测试表结构如下:
CREATE TABLE test1_byxx
(
id
bigint(20) NOT NULL AUTO_INCREMENT,
name
varchar(20) NOT NULL DEFAULT ‘’,
uid
int(11) NOT NULL DEFAULT 0,
ctime
datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,
mtime
datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’,
PRIMARY KEY (id
),
UNIQUE KEY uk_uid
(uid
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=1
【附件】
请提供各个组件的 version 信息,如 cdc/tikv,可通过执行 cdc version/tikv-server --version 获取。