pingcap / pingcap/tidb

ADD [UNIQUE] INDEX ... GLOBAL can leave an incomplete global index on a partitioned table after EXCHANGE PARTITION ... WITHOUT VALIDATION duplicates a primary key

Open
#70,932 2 comments 0 reactions 1 assignee Claimed by @expxiaoli View on GitHub
affects-25.10 affects-26.3 affects-7.5 affects-8.1 affects-8.5 affects-9.0 component/ddl found-by-ai severity/major sig/sql-infra type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

```sql
SET GLOBAL tidb_enable_exchange_partition = 1;
SET GLOBAL tidb_ddl_enable_fast_reorg = 0;

CREATE TABLE t(
a INT, b INT, c VARCHAR(20),
PRIMARY KEY(a,b) -- clustered
)
PARTITION BY RANGE (b) (
PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20),
PARTITION pmax VALUES LESS THAN (MAXVALUE)
);
INSERT INTO t VALUES (1,1,'x');

CREATE TABLE tx LIKE t;
ALTER TABLE tx REMOVE PARTITIONING;
INSERT INTO tx VALUES (1,1,'x');

ALTER TABLE t EXCHANGE PARTITION p1 WITH TABLE tx WITHOUT VALIDATION;
SELECT COUNT(*) FROM t; -- 2

ALTER TABLE t ADD UNIQUE KEY ug(c) GLOBAL;

SELECT COUNT(*) FROM t; -- 1 (uses the new global index)
SELECT COUNT(*) FROM t IGNORE INDEX(ug); -- 2 (table scan)

ADMIN CHECK TABLE t;
-- ERROR 8223: data inconsistency in table: t, index: ug,
-- index-values:"" != record-values:"... values: [KindString x]"
```

With `tidb_ddl_enable_fast_reorg = 1`, `ADD UNIQUE KEY ... GLOBAL` correctly
errors 1062 and preserves both rows. A global **non-unique** index
(`ALTER TABLE t ADD INDEX idx_c(c) GLOBAL`) after the same duplicate-PK state
leaves `ADMIN CHECK TABLE` 8223 on both the fast/dist and legacy paths.

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

`ADD [UNIQUE] INDEX ... GLOBAL` must either build one complete index entry per
table row or fail with a duplicate-key error. It must never leave an index
missing entries.

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

On the legacy path the DDL succeeds but the new global index has only one
entry for two table rows; index scans and table scans return different row
counts, and `ADMIN CHECK TABLE` reports 8223. Dropping the incomplete index
restores consistency (table rows are intact).

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

```
Release Version: v8.4.0-this-is-a-placeholder
Edition: Community
Git Commit Hash: None
Git Branch: None
UTC Build Time: None
```

Built from source commit `a514a92784c9654502686e6ee6efc9e0aeda8afa` (pingcap/tidb master, 2026-09-07).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.