myisam表压缩后天然只读,必须先用myisampack压缩,再用myisamchk -rq重建索引,否则无法访问;压缩表不支持任何dml,且ddl不可逆,须在压缩前完成结构优化与权限隔离。

MyISAM 表压缩后天然只读,但必须配合 myisampack 和 myisamchk
MyISAM 本身不支持事务或行级锁,但它的“静态压缩”特性是构建只读归档库最轻量、最直接的手段:压缩后的表文件(.MYD)被标记为只读,任何 INSERT/UPDATE/DELETE 都会立即报错 ERROR 1036 (HY000): Table 'xxx' is read only。这不是靠 MySQL 权限控制,而是引擎层硬限制。
关键操作链不能跳步:
- 先用
myisampack -b -f /var/lib/mysql/dbname/tablename.MYI压缩表(-b保留备份,-f强制覆盖) - 压缩后必须运行
myisamchk -r -f /var/lib/mysql/dbname/tablename.MYI重建索引,否则表无法打开 - 重启 mysqld 或执行
FLUSH TABLES,让 MySQL 重新加载表结构和只读状态
注意:myisampack 只接受未加密、非分区、无全文索引的 MyISAM 表;若表含 FULLTEXT 索引,需先 DROP INDEX 再压缩,归档库通常也不需要全文检索。
全局 read_only=ON 对 MyISAM 归档库无效,得靠 innodb_read_only=1 + 文件权限双保险
很多人误以为设了 SET GLOBAL read_only = ON 就万事大吉——但它对 MyISAM 表基本没用。MyISAM 不走 MySQL 的写入拦截路径,只要用户有文件系统写权限,仍可能通过直接修改 .MYD 文件绕过 SQL 层限制。
真正能锁死 MyISAM 归档库的组合是:
-
innodb_read_only = 1(MySQL 8.0+):虽名含 InnoDB,但它会禁止所有存储引擎的 DDL(包括CREATE TABLE、DROP TABLE),防止有人新建表覆盖归档数据 - 操作系统层加固:执行
chown mysql:mysql /var/lib/mysql/archive_db/*.MYD后,再chmod 444 /var/lib/mysql/archive_db/*.MYD,彻底移除写权限 - 禁用
skip_grant_tables并确保没有本地 root 免密登录,避免绕过权限检查
单独依赖任一措施都存在缺口:innodb_read_only 需重启生效且不拦文件操作;chmod 444 不防 MySQL 进程自身(它以 mysql 用户运行),所以二者必须共存。
归档库命名与连接隔离:用 archive_ 前缀 + 显式 transaction_read_only=1
业务代码常混用主库和归档库连接,哪怕归档库物理只读,一旦应用误发写语句(比如 ORM 自动生成的 INSERT INTO SELECT),仍会触发错误中断。最稳妥的做法是:在连接串里强制开启会话级只读,让写操作在语法解析阶段就失败,而不是等到执行时才报错。
例如使用 MySQL 8.0+ 客户端连接归档库时,在 DSN 中加入:?transaction_read_only=1&read_timeout=30。这样即使连接到了一个未压缩的 MyISAM 表,也会在事务内拒绝所有 DML。
同时,归档库名必须带明确前缀,如 archive_orders_2024 或 hist_logs_q1。不要用 backup、old 这类模糊词——运维脚本、监控告警、权限策略全靠库名识别用途。DBA 批量回收权限时,GRANT SELECT ON `archive_%`.* TO 'reporter'@'%' 这种通配才可靠。
MyISAM 归档库无法在线变更结构,DDL 必须在迁移前完成
一旦表被 myisampack 压缩,就再也无法执行 ALTER TABLE、ADD COLUMN、OPTIMIZE TABLE 等任何 DDL。连 ANALYZE TABLE 都会被 innodb_read_only=1 拦住(因为它要更新数据字典)。
这意味着所有结构调整必须在数据迁入归档库之前做完:
- 删掉无用索引(归档库查询模式固定,索引反而占空间)
- 把
VARCHAR改成CHAR(静态格式提升压缩率) - 确认字符集统一为
utf8mb4,避免后续跨库 JOIN 出乱码 - 用
mysqldump --no-create-info --skip-triggers导出纯数据,再导入到已建好结构的归档库中
漏掉这一步,后期发现少了个字段或索引错了,只能解压→改结构→重压→重校验,整个归档流程就得重来。归档不是 dump & load,而是结构+数据+权限+访问策略的一体化交付。











