MySQL无法直接限制表空间大小,唯一有效方案是启用innodb_file_per_table后配合Linux文件系统quota机制限制mysql用户磁盘配额。

MySQL 表空间无法直接按“大小”限制,innodb_file_per_table 是前提
MySQL 本身不支持对单个表或表空间设置磁盘配额(比如“这个表最多用 2GB”)。你看到的 DATA_LENGTH 或 INDEX_LENGTH 只是统计值,改不了实际写入行为。真正能间接控制增长的,是开启 innodb_file_per_table —— 它让每张 InnoDB 表对应一个独立的 .ibd 文件,后续才能配合文件系统级手段做约束。
没开这个选项时,所有表都挤在共享表空间 ibdata1 里,根本没法单独限大小。
- 检查是否启用:
SHOW VARIABLES LIKE 'innodb_file_per_table';,返回ON才有效 - 新库默认开启;老库需手动设为
1并重启,但已有表不会自动迁移,得ALTER TABLE t ENGINE=InnoDB;重建 - 注意:开启后
ibdata1仍会增长(存元数据、undo log 等),不能指望它变小
Linux 文件系统配额是唯一可行的“硬限制”方案
MySQL 层面做不到,就得下到 OS 层——给 MySQL 数据目录所在挂载点启用用户/组配额(quota),把 mysqld 进程运行用户(通常是 mysql)设上限。这是目前唯一能真正阻止写满的机制。
- 必须是支持配额的文件系统(如 ext4、xfs),且挂载时带
usrquota或grpquota选项 - 配额对象是用户或组,不是数据库名或表名;确认
mysqld以mysql用户运行:ps aux | grep mysqld - 配额生效后,当表写入触发
.ibd扩展超过限额,MySQL 会报错:ERROR 1114 (HY000): The table 't' is full,而非静默失败 - 别用
du实时查配额用量,要用quota -u mysql或repquota
max_rows 和 avg_row_length 是伪限制,慎用
建表时设 MAX_ROWS=1000000 AVG_ROW_LENGTH=2048,看起来像在限大小,其实只是优化器估算依据,MySQL 完全不强制执行。InnoDB 忽略这两个参数,MyISAM 也只在创建时参考,后续照常插入。
- 不会阻止 INSERT,不会触发警告或错误
- 可能误导
SHOW TABLE STATUS中的DATA_LENGTH预估,但实际文件大小由真实数据决定 - 唯一影响:MyISAM 的
DATA_FILE_LENGTH统计值会据此调整,无实质约束力
监控比限制更现实,information_schema.INNODB_SYS_TABLESPACES 要定期查
与其花力气搞不可靠的“限制”,不如盯紧增长趋势。InnoDB 提供了真正的表空间大小视图,比 TABLES 表更准(后者依赖采样,常不准)。
- 查单表空间大小(字节):
SELECT NAME, FILE_SIZE, ALLOCATED_SIZE FROM information_schema.INNODB_SYS_TABLESPACES WHERE NAME = 'db/t'; -
FILE_SIZE是文件系统实际大小,ALLOCATED_SIZE是 InnoDB 认为已分配的空间(含碎片) - 搭配定时任务(如每小时跑一次)+ 告警阈值(比如 >50GB 或周增 >10GB),比任何“配额”都早发现问题
- 注意:该视图需要
PROCESS权限,普通应用账号通常没有
真要控大小,核心就两条:确保 innodb_file_per_table=ON,然后在文件系统层用 quota 卡住 mysql 用户。其他所有“表级限制”都是障眼法,连警告都不会给你。


















