stats: DDL stats meta update can deadlock with analyze save on mysql.stats_meta
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
### 1. Minimal reproduce step (Required)
1. Start a **real TiKV** cluster.
2. Create and analyze a tiny table so a real `mysql.stats_meta` row exists:
```sql
create table test.t_deadlock_repro (a int primary key, b int, key idx_b(b));
insert into test.t_deadlock_repro values (1,1),(2,2),(3,3);
analyze table test.t_deadlock_repro all columns;
```
3. Get its `tidb_table_id`:
```sql
select tidb_table_id
from information_schema.tables
where table_schema='test' and table_name='t_deadlock_repro';
```
4. Split both `mysql.stats_meta` row keys and `tbl(table_id)` index keys into many regions to widen the timing window:
```sql
split table mysql.stats_meta between (0) and (2000000) regions 32;
split table mysql.stats_meta index tbl between (-2000000) and (2000000) regions 32;
```
5. Concurrently run these two pessimistic transactions in a short loop:
- DDL stats update side:
```sql
begin pessimistic;
select count, modify_count from mysql.stats_meta where table_id = for update;
```
- Analyze save side:
```sql
begin pessimistic;
select snapshot, count, modify_count from mysql.stats_meta where table_id in (-, ) for update;
```
6. Check `information_schema.deadlocks`.
### 2. What did you expect to see? (Required)
No deadlock between the DDL-side stats meta update path and the analyze-save path.
### 3. What did you see instead (Required)
`information_schema.deadlocks` records the exact SQL pair above. On the client side this can surface as `Error 1213 (40001): Deadlock found when trying to get lock`.
The two code paths are:
- DDL side: `pkg/statistics/handle/ddl/ddl.go` -> `StatsMetaCountAndModifyCountForUpdate()`
- Analyze side: `pkg/statistics/handle/storage/save.go`
This looks like the same underlying lock-order class already described in `save.go`: point get vs batch point get on `mysql.stats_meta` acquire locks in different orders. The current `fakeID := -tableID` mitigation reduces contention but does not eliminate the deadlock class.
### 4. What is your TiDB version? (Required)
Reproduced on current master `fd7c13a934` with a locally built `tidb-server` binary plus TiUP nightly PD/TiKV on real TiKV.
Contributor guide
Assessment
This issue has not been assessed yet.