会,且是确定性损坏;mysql异常终止时未刷盘的索引变更永久丢失,导致select出错、check table报错126、repair table可能失败。

DELAY_KEY_WRITE 会导致索引损坏吗
会,而且是确定性损坏。只要 MySQL 进程异常终止(比如 kill -9、OOM killer 干掉 mysqld、系统断电),所有尚未刷盘的索引变更就永久丢失。此时 SELECT 可能返回错误结果,CHECK TABLE 会报 error: 126 (Incorrect key file for table) 或类似索引校验失败,REPAIR TABLE 可能失败或需要强制介入。
为什么 --myisam-recover 不是可选项而是强制前提
因为 DELAY_KEY_WRITE 本身不提供任何恢复能力,它只负责“缓存+延迟写”,而修复责任完全交给启动时的自动检查机制。不配 --myisam-recover=FORCE,BACKUP 或配置文件中等效的 myisam-recover=FORCE,BACKUP,MySQL 启动时不会扫描 MyISAM 表、不会触发自动修复,损坏索引就会静默带病运行——你查不到错,但数据不可信。
-
FORCE:强制检查并尝试修复所有 MyISAM 表,即使没报错 -
BACKUP:修复前先备份原始 .MYI 文件,留痕可回溯 - 缺一不可;只写
myisam-recover=ON在新版 MySQL 中已无效
全局 delay_key_write 设置对安全的影响
这个变量直接控制 DELAY_KEY_WRITE 的生效范围,但它不改变风险本质:
-
SET GLOBAL delay_key_write = 'OFF':全局禁用,哪怕表定义里写了DELAY_KEY_WRITE=1也无效 -
SET GLOBAL delay_key_write = 'ON':仅对显式声明了DELAY_KEY_WRITE=1的表启用——这是最可控的方式 -
SET GLOBAL delay_key_write = 'ALL':所有 MyISAM 表无条件启用延迟索引写入,包括系统表(如mysql.host)——风险面极大,不推荐
注意:delay_key_write 是全局动态变量,但修改后不会影响已打开的表,只对新打开的表生效;生产环境务必写进 my.cnf 并重启 mysqld,避免服务重启后配置丢失。
实际运维中最容易被忽略的三个点
第一,SHOW CREATE TABLE 输出里看到 DELAY_KEY_WRITE=1 ≠ 真的在用——必须确认 delay_key_write 全局变量是 ON 或 ALL;
第二,FLUSH TABLES 或缓存淘汰触发的“表关闭”不是即时的,高峰期可能几十秒甚至几分钟才刷一次索引,这期间全是裸奔窗口;
第三,MyISAM 本身不支持事务和崩溃安全,DELAY_KEY_WRITE 只是放大了它的脆弱性,而不是引入新问题——如果你已经在用 MyISAM,那索引损坏本就是日常风险,只是这个开关让它更频繁、更隐蔽。











