myisam不支持行级锁,高并发写入易成瓶颈;innodb需用自增主键避免页分裂;分区表仅在查询含分区字段时生效;大字段应拆至子表并压缩存储。

MyISAM 不支持行级锁,高并发写入时会成为扩展瓶颈
MyISAM 引擎在执行 UPDATE 或 DELETE 时会对整张表加锁,哪怕只改一行,其他写请求也得排队。这在用户量上涨、写操作变多时,Waiting for table metadata lock 错误会频繁出现。
实操建议:
- 如果业务有持续的写入压力(如日志记录、订单生成),别用 MyISAM
- 迁移存量表前,先用
SHOW CREATE TABLE `table_name`确认当前引擎,再用ALTER TABLE `table_name` ENGINE=InnoDB切换 - InnoDB 支持事务和行锁,但要注意:没走索引的
UPDATE或DELETE仍可能升级为表锁
InnoDB 的主键设计直接影响插入性能与数据分布
InnoDB 表数据按主键顺序物理存储(聚簇索引)。如果主键是随机值(比如 UUID 或雪花 ID),新记录会不断插入到页中间,引发大量页分裂和磁盘随机写,吞吐量随数据量增长明显下降。
实操建议:
- 优先用自增
BIGINT作主键,保证写入集中在 B+ 树最右端 - 若必须用业务 ID(如订单号),确保它是时间递增的(例如
20240520123456),避免全随机 - 不要把长字符串(如邮箱)设为主键,B+ 树节点存不下多少条记录,深度增加,查询变慢
分区表不是万能扩展方案,反而可能拖慢简单查询
MySQL 的原生分区(PARTITION BY RANGE / LIST / HASH)只在查询条件带上分区字段时才生效。否则优化器会扫描所有分区,比单表还慢 —— 尤其当分区数超过 32 个后,元数据开销显著上升。
实操建议:
- 只对「按时间归档」或「按租户隔离」这类明确可裁剪数据范围的场景考虑分区
- 分区字段必须是主键/唯一键的一部分,否则建表失败;这意味着你不能随便拿
created_at分区,除非它也在主键里 - 真正需要水平扩展时,优先考虑应用层分库分表(如 ShardingSphere),而不是依赖 MySQL 分区
大字段(TEXT/BLOB)放在单独子表里,避免主表膨胀影响缓存效率
InnoDB 的 Buffer Pool 缓存的是整页(默认 16KB),只要一页里有一行带大字段,整页就很难被复用。随着数据增长,Buffer Pool 命中率下降,磁盘 I/O 暴涨,查询延迟波动剧烈。
实操建议:
- 把
content、attachment_data这类字段拆到独立表,用外键关联,主表只留 ID 和摘要字段 - 子表可以单独设置
ROW_FORMAT=COMPRESSED并调小KEY_BLOCK_SIZE,节省空间 - 注意:拆表后
JOIN查询变多,需权衡读多还是写多;高频读场景下,可加一层 Redis 缓存组合结果
WHERE 条件、一个未压缩的 BLOB 字段、或者分区策略和查询模式错配。这些细节不会立刻报错,但会在数据量突破千万后集中爆发。










