pingcap / pingcap/tidb

[br] BR can restore into a concurrently created incompatible table and report success with a corrupted index

Open
#70,095 0 comments 0 reactions 0 assignees View on GitHub
component/br found-by-ai may-affects-7.5 may-affects-8.1 may-affects-8.5 severity/critical type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

### 1. Minimal reproduce step (Required)

**Environment**

master 05b396fb6636; verified BR a942e4684f43

**Steps**

Back up t(id PK,a,b,UNIQUE uk(a)). Drop t and start br restore table with default checkpoint mode. After the precheck has passed and checkpoint initialization begins, concurrently create t(id PK,a,b,UNIQUE uk(b)). Wait for BR success, then force uk for WHERE b=10 and run ADMIN CHECK TABLE.

### 2. What did you expect to see? (Required)

The restore must atomically claim the target table identity. If another actor creates the name after admission, BR must fail before generating rewrite rules or ingesting KVs unless the exact expected schema and identity are proven compatible.

### 3. What did you see instead? (Required)

Two independent runs exited 0, reported Table Restore success, and validated checksum. The table kept uk(b), but its restored index keys encoded backup column a. WHERE b=10 returned a row with b=100, WHERE b=100 returned no row, ADMIN CHECK returned 8223, and UPDATE ... WHERE b=10 successfully modified the b=100 row.

### 4. What is your TiDB version? (Required)

master 05b396fb6636; verified BR a942e4684f43

Likely root cause and fix direction

**Likely root cause**

checkTableExistence proves absence only at one InfoSchema snapshot. BR later calls BatchCreateTableWithInfo with OnExistIgnore, so a concurrent CREATE is treated as successful BR creation. SnapClient then reacquires the table by name, checks only IsCommonHandle, and GetIndexIDMap maps indexes solely by name before physical ingest.

**Fix direction**

Use an atomic target-name claim or make BR table creation fail on existence after the precheck. Bind every rewrite rule to the exact table ID created by BR. If idempotent reuse is required, compare a full restore-relevant schema fingerprint, including columns, types, defaults, generated expressions, primary handle, indexes, constraints, and special metadata, before ingest.

Contributor guide

Open the contributing guide

Research direction

Trace checkTableExistence, BatchCreateTableWithInfo, SnapClient, and GetIndexIDMap through the BR restore path, then reproduce the concurrent CREATE scenario described above. Verify that an incompatible table cannot be claimed or ingested into, and that the restore fails without leaving mismatched index keys or reporting success.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
databases, distributed-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.