MySQL分区数上限为128个,超限会触发open_files_limit导致启动失败;RANGE分区单区不宜超1500万行,HASH分区数应为16/32/64且不超64;LIST分区单区枚举值不超过32个。
分区数量超过128个会直接触发 open_files_limit 限制
MySQL 5.7 对每个分区都持有一个独立的
文件句柄,分区数一多,
很快就耗尽。现象是启动失败或报错
,尤其在
值偏高时更明显。
实操建议:
硬性上限卡死在
个分区以内——不是“建议”,是避免启动失败的底线
若当前已有超限分区表,别急着删数据,先用
退化为普通表,再按需重建
检查实际使用:运行
确认真实分区数
SSD 环境下也别盲目堆到 128,NVMe 上压到
更稳妥,留余量给其他表和系统文件
RANGE 分区单分区超 1500 万行会导致 B+ 树层级膨胀
时间类 RANGE 分区(比如按月/按天)最容易踩这个坑:初期数据少,分区建得细;后期单分区暴涨,查询反而变慢。因为 InnoDB 的 B+ 树页层级随数据量增加,超过 1500 万行后,深度从 3 层涨到 4 层,每次索引查找多一次磁盘 IO。
实操建议:
OLTP 场景严格控制在
万行/分区;OLAP 可放宽到
万,但绝不可碰
万红线
已有超大分区,优先用
合并,而不是
——后者会锁全表且重建索引
按天分区的表,如果日均写入
万行,三个月就逼近临界点,这时该切到按周或按月
必须定期跑,确认查询是否真的只打到目标分区,避免隐式全分区扫描
HASH 分区数不是越多越好,必须是 2 的幂次且 ≤64
HASH 分区靠取模路由,分区数非 2 的幂次会导致数据倾斜。比如设
,实际分布严重不均,某些分区挤占 40% 数据,其他空转。同时,HASH 分区数超过
后,哈希冲突概率陡增,
性能不升反降。
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
实操建议:
固定用
、
、
这三个值,别试
或
用户 ID 类整型主键,优先选
;若总数据量不到 5000 万,
更省内存
别对字符串字段直接 HASH——先用
或
转成整型再分区,否则效率极低
监控
中的
,任一分区偏差超 ±25%,就要重估分区数
LIST 分区枚举值过多会拖慢元数据加载
LIST 分区依赖显式值映射(
),当一个分区里塞了上百个 province_id 或 status_code,MySQL 每次打开表都要解析整个枚举列表,导致
占用飙升,冷启动变慢。
实操建议:
单个 LIST 分区的枚举值别超
个;超了就拆成多个分区,比如
和
避免用动态生成的枚举(如时间戳、UUID 片段),LIST 只适合稳定、有限、业务可归类的维度
如果枚举集合会频繁增删,改用 RANGE 或 HASH + 查找表(lookup table)替代 LIST
用
检查 DDL,确认没有类似
这种长列表直写
真正难处理的不是分区逻辑本身,而是分区与 buffer pool、open_files_limit、table_definition_cache 这三者的耦合关系——调一个参数,另外两个可能立刻告警。动手前务必先查
和
,再决定动不动分区。
.ibdopen_files_limitERROR 23 (HY000): Out of resources when opening filetable_open_cache128ALTER TABLE ... REMOVE PARTITIONINGSELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 'your_table';96200–500500–10002000ALTER TABLE ... REORGANIZE PARTITIONDROP + ADD20EXPLAIN PARTITIONSPARTITIONS 3064INSERT1632644856PARTITIONS 6432CRC32()MURMUR_HASH()INFORMATION_SCHEMA.PARTITIONSTABLE_ROWSVALUES IN (1,2,3,...)table_definition_cache32p_east_1p_east_2SHOW CREATE TABLEVALUES IN (1,2,3,...,256)SHOW VARIABLES LIKE '%open_files%';SHOW STATUS LIKE 'Open_tables';