MySQL 5.1 分區表強制要求:**每個唯一索引 (含主鍵) 的所有欄位,必須包含分區鍵欄位**。違反即報錯 ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function。本文通過實驗演示該限制的具體表現與繞過策略。
Partitioning Keys ⊆ Unique Keys:分區鍵欄位集合必須是每個唯一索引欄位集合的子集。
CREATE TABLE t1 (
id INT NOT NULL,
uid INT NOT NULL,
PRIMARY KEY (id)
)
PARTITION BY RANGE (id) (
PARTITION p0 VALUES LESS THAN (5) ENGINE=INNODB,
PARTITION p1 VALUES LESS THAN (10) ENGINE=INNODB
);
-- Query OK
主鍵 (id) 包含分區鍵 id,通過。
CREATE TABLE t1 (
id INT NOT NULL,
uid INT NOT NULL,
PRIMARY KEY (id)
)
PARTITION BY RANGE (uid) ( -- 分區鍵為 uid
PARTITION p0 VALUES LESS THAN (5),
PARTITION p1 VALUES LESS THAN (10)
);
-- ERROR 1503: A UNIQUE INDEX must include all columns in the table's partitioning function
主鍵 (id) 不包含分區鍵 uid,失敗。
CREATE TABLE t1 (
id INT NOT NULL,
uid INT NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (uid)
)
PARTITION BY RANGE (id) (
PARTITION p0 VALUES LESS THAN (5),
PARTITION p1 VALUES LESS THAN (10)
);
-- ERROR 1503: UNIQUE KEY (uid) 不包含分區鍵 id
| 模式 | 分區鍵 | 主鍵/唯一索引 | 合法性 |
|---|---|---|---|
| 主鍵即分區鍵 | id | PRIMARY KEY (id) | ✅ |
| 複合主鍵含分區鍵 | id | PRIMARY KEY (id, uid) | ✅ |
| 複合唯一索引含分區鍵 | id | UNIQUE KEY (id, email) | ✅ |
| 唯一索引缺分區鍵 | id | UNIQUE KEY (email) | ❌ |
UNIQUE KEY (id, email),但改變語義 (同 email 可在不同分區重複)INDEX (email),定期跑批一致性掃描PARTITION BY KEY、SUBPARTITION,但核心規則未變MySQL 分區表的唯一約束限制本質上是為了**分區裁剪時的唯一性檢查效能**:若唯一索引不含分區鍵,插入時需跨所有分區檢查唯一性,敗壞分區性能初衷。設計時**優先讓分區鍵成為主鍵前綴**,或接受「應用層去重 + 普通索引」的工程妥協。