MySQL 5.1+ 支援分區表,且允許為每個分區指定獨立的資料檔案與索引檔案儲存路徑(DATA DIRECTORY、INDEX DIRECTORY)。這對於將熱點分區放置 SSD、冷數據歸檔 HDD、分散 I/O 壓力至多磁碟極具價值。本文詳細解析配置語法、引擎支援度、權限要求與避坑指南。
CREATE TABLE users (
uid INT UNSIGNED NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL DEFAULT '',
email VARCHAR(30) NOT NULL DEFAULT ''
)
PARTITION BY RANGE (uid) (
PARTITION p0 VALUES LESS THAN (3000000)
DATA DIRECTORY = '/data0/data'
INDEX DIRECTORY = '/data1/idx',
PARTITION p1 VALUES LESS THAN (6000000)
DATA DIRECTORY = '/data2/data'
INDEX DIRECTORY = '/data3/idx',
PARTITION p2 VALUES LESS THAN (9000000)
DATA DIRECTORY = '/data4/data'
INDEX DIRECTORY = '/data5/idx',
PARTITION p3 VALUES LESS THAN MAXVALUE
DATA DIRECTORY = '/data6/data'
INDEX DIRECTORY = '/data7/idx'
);
| 儲存引擎 | DATA DIRECTORY | INDEX DIRECTORY | 備註 |
|---|---|---|---|
| MyISAM | ✅ 全支援 | ✅ 全支援 | .MYD/.MYI 物理檔案可獨立放置 |
| InnoDB | ❌ 不支援 (5.6 及之前) | ❌ 不支援 | 所有分區共享表空間 ibdata1 或 .ibd |
| InnoDB | ⚠️ 部分支援 (5.7+) | ⚠️ 部分支援 | innodb_file_per_table=ON 時,ALTER TABLE ... PARTITION ... DATA DIRECTORY 可移動單個分區 .ibd |
| NDB Cluster | ✅ 支援 | ✅ 支援 | 分散式架構原生支援 |
結論:若需使用 DATA/INDEX DIRECTORY 將分區分散至多磁碟,**MyISAM 是原生最佳選擇**;InnoDB 5.7+ 需開啟獨立表空間並透過 ALTER TABLE 遷移,操作較繁瑣。
mkdir -p /data0/data /data1/idx /data2/data /data3/idx ...
chown -R mysql:mysql /data0 /data1 /data2 /data3 ...
chmod 750 /data0 /data1 /data2 /data3 ...
skip_symbolic_links:
[mysqld]
skip_symbolic_links = OFF # 預設 OFF,若開啟會導致失效
[mysqld]
innodb_file_per_table = ON
# 可選:指定預設資料/索引目錄(不指定則用 datadir)
# innodb_data_home_dir = /data/mysql
# innodb_log_group_home_dir = /data/mysql/logs
# 假設掛載 4 塊磁碟:/mnt/ssd0 /mnt/ssd1 /mnt/hdd0 /mnt/hdd1
for d in /mnt/ssd0/data /mnt/ssd0/idx /mnt/ssd1/data /mnt/ssd1/idx /mnt/hdd0/data /mnt/hdd0/idx /mnt/hdd1/data /mnt/hdd1/idx; do
mkdir -p $d
done
chown -R mysql:mysql /mnt/ssd0 /mnt/ssd1 /mnt/hdd0 /mnt/hdd1
CREATE TABLE sensor_log (
id BIGINT UNSIGNED NOT NULL,
sensor_id INT NOT NULL,
log_time DATETIME NOT NULL,
value DOUBLE NOT NULL,
PRIMARY KEY (id, log_time)
)
PARTITION BY RANGE (YEAR(log_time)) (
PARTITION p2020 VALUES LESS THAN (2021)
DATA DIRECTORY = '/mnt/hdd0/data' INDEX DIRECTORY = '/mnt/hdd0/idx',
PARTITION p2021 VALUES LESS THAN (2022)
DATA DIRECTORY = '/mnt/hdd0/data' INDEX DIRECTORY = '/mnt/hdd0/idx',
PARTITION p2022 VALUES LESS THAN (2023)
DATA DIRECTORY = '/mnt/ssd0/data' INDEX DIRECTORY = '/mnt/ssd0/idx',
PARTITION p2023 VALUES LESS THAN (2024)
DATA DIRECTORY = '/mnt/ssd1/data' INDEX DIRECTORY = '/mnt/ssd1/idx',
PARTITION pmax VALUES LESS THAN MAXVALUE
DATA DIRECTORY = '/mnt/ssd1/data' INDEX DIRECTORY = '/mnt/ssd1/idx'
) ENGINE = MyISAM;
# 檢查資料目錄下的符號連結
ls -la /var/lib/mysql/mydb/
# sensor_log#P#p2020.MYD -> /mnt/hdd0/data/sensor_log#P#p2020.MYD
# sensor_log#P#p2020.MYI -> /mnt/hdd0/idx/sensor_log#P#p2020.MYI
# 或查詢分區資訊
SELECT PARTITION_NAME, DATA_DIRECTORY, INDEX_DIRECTORY
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'sensor_log';
| 錯誤現象 | 原因 | 解決 |
|---|---|---|
| ERROR 1005 (HY000): Can't create table | 目錄不存在 / 權限不足 / 檔案系統不支援符號連結 | 建立目錄、chown mysql:mysql、檢查 skip_symbolic_links |
| 分區建立成功但檔案仍在 datadir | 引擎不支援(InnoDB < 5.7) | 改用 MyISAM 或升級 InnoDB + ALTER TABLE 遷移 |
| REPAIR TABLE / OPTIMIZE TABLE 失效 | MyISAM 分區表操作會重建檔案,可能破壞符號連結 | 操作前備份,操作後檢查並修復連結 |
| 備份工具 (mysqldump/xtrabackup) 異常 | 部分舊版工具不識別分區符號連結 | 使用新版工具或邏輯備份 |
| DROP PARTITION 後磁碟空間未釋放 | 符號連結刪除但目標檔案殘留 | 手動清理目標目錄殘留檔案 |
-- 建立表時不指定目錄(使用預設 datadir)
CREATE TABLE t (id INT PRIMARY KEY, dt DATE)
PARTITION BY RANGE (YEAR(dt)) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022)
) ENGINE=InnoDB;
-- 事後遷移冷分區至 HDD
ALTER TABLE t REORGANIZE PARTITION p2020 INTO (
PARTITION p2020 VALUES LESS THAN (2021) DATA DIRECTORY = '/mnt/hdd0/data'
);
需 innodb_file_per_table=ON,操作會鎖表重建 .ibd,大表建議低峰期執行。
DATA DIRECTORY/INDEX DIRECTORY 是 MySQL 分區表實現儲存分級的核心功能。**MyISAM 原生完美支援**,InnoDB 5.7+ 需配合獨立表空間與 ALTER TABLE 實現。生產落地關鍵在於:**目錄預建與權限、檔案系統符號連結支援、備份工具相容性測試、監控實際 I/O 分布驗證效果**。