update执行时间长,偶尔出现超时Lock wait timeout exceeded; try restarting transaction

【 TiDB 使用环境】版本4.0.8

【概述】 update执行时间长,偶尔超时Lock wait timeout exceeded; try restarting transaction

【背景】
tidb_txn_mode pessimistic
表 t 数据量3w ,
表结构
create table t (
id bigint not null auto_random,
c1 varchar(100),
c2 varchar(768),
c3 varchar(1024),
c4 int,

primary key (id),
key idx1(c1),
key idx2(c2),
key idx3(c5,c6,c7,c8),
key idx4(c6,c5,c7,c8));

update语句:
update t set c4=0 where c1=‘xxx’ and c2=‘xxx’ and c4=1;

【现象】
执行update,耗时20s左右,偶尔50s+超时。
执行计划:
id task actrows operator info execution info
update_5 root 0 N/A time:24.99527s,loops:2, …
SelectLock_7 root 2 for update time:24.99508s,loops:4
IndexLookup18 root 2 time:3.96151s,loops:4…
IndexScan15 cop[tikv] 3 table:t index:idx2(c2),range… proc max:1ms,min:1ms
Selection17 cop[tikv] 0 eq(t.c4,1),eq(t.c1,xxx) time:0ns,loops:0
TableScan16 cop[tikv] 0 table:t, keep order:false time:0ns,loops:0

执行时间:
解析耗时 72.6us
优化耗时 444.8us
Coprocessor累积等待耗时 0ns
Coprocessor累积执行耗时 1ms
累计重试等待耗时 0ns
取commit Ts耗时 0ns
Local Latch Wait耗时 0ns
Resolve Lock耗时 0ns
Prewrite阶段耗时 0ns
Commit阶段耗时 0ns
Commit重试等待耗时 0ns
SQL执行时间 25s

Coprocessor读取:
Coprocessor请求数 2
可见版本数 4
遇到版本数 5
最长处理时间实例 xxxx
最长等待时间实例 xxxx

事务:
事务号 xxxxx
写入Key个数 0
写入数据量 0B
Prewrite涉及Regions个数 0
事务重试次数 0

【问题】
1、如何排查耗时?
2、如何判断执行时间长的原因,如何优化?

学会看执行计划就可以排查耗时了,这个执行计划中有TableScanIndexScan前者是扫了全表,后者扫了idx2(c2)整个索引,都比较耗时。
关注执行计划可以参考 EXPLAIN 概览 | PingCAP Docs

全表只有3w数据,即使扫描全表也就花了3s,后面selectlock花了24s,请问selectlock是什么动作,为什么会需要这么长时间?

这是被锁住了:thinking:,要检查一下锁冲突的问题

创建一个c4的索引试试?

c4 只有0和1两个值,且0占80%,创建索引会有效吗?

从Grafana 的 KV Errors 中看,
Lock Resolve OPS 面板中,not_expired 和 resolve 分别为0.0444 和 0.0667
KV Backoff OPS面板中,没有出现 tikvLockFast 指标和 txnLock 指标
是否说明没有出现读写冲突?

看你的查询是c4=1,这个可以过滤掉很多记录了吧?那这个索引就有效,你可以测试一下。

好的,我先试试

这么看来好像是没有冲突,但是执行计划里面的算子应该是有锁,比较奇怪。等大佬看看这是啥情况吧