myisam高并发写入会整表锁死、宕机易丢数据且删旧低效;innodb支持行级锁、崩溃自动恢复、分区truncate,更适合游戏日志场景。

游戏日志写入高并发时MyISAM会整表锁死
游戏日志典型特征是高频 INSERT + 偶尔 SELECT(比如查某玩家昨日行为),MyISAM 在每次 INSERT 时都会加表级写锁,期间所有 SELECT、UPDATE 全部排队。哪怕只有一条慢查询卡住,后续几千条日志写入就全堵在锁队列里——线上常表现为“日志延迟突增”或“写入超时”。InnoDB 默认行级锁,只要日志表有主键或自增 ID,每条插入只锁自己那行,互不干扰。
崩溃后日志丢失风险不可控
游戏服务偶发宕机或强制 kill mysqld 进程很常见。MyISAM 没有事务日志,.MYD 或 .MYI 文件损坏后必须执行 REPAIR TABLE,而该命令在 MySQL 5.7+ 默认被禁用,需手动配置 myisam_recover_options 才能启用;即便启用,TB 级日志表修复可能耗时数小时,且存在静默丢数据风险。InnoDB 依赖 ib_logfile0 和双写缓冲,重启时自动前滚已提交、回滚未提交,整个过程秒级完成,日志一条不丢。
日志表需要按玩家ID或时间范围快速删旧数据
游戏日志库通常要定期清理 30 天前的数据。MyISAM 不支持外键,也没分区表的原生 TRUNCATE 分区能力;想删老数据只能 DELETE FROM log_table WHERE create_time ,这会触发全表扫描+全表锁,阻塞新日志写入。InnoDB 支持 <code>PARTITION BY RANGE (TO_DAYS(create_time)),配合 ALTER TABLE ... DROP PARTITION 可毫秒级删除整个月份分区,且不影响其他分区读写。
全文检索需求其实可以绕过MyISAM
有人留恋 MyISAM 的全文索引,想搜“玩家A 使用了 飞行坐骑”。但 InnoDB 自 1.2.x 起已支持 FULLTEXT 索引,建表时加 FULLTEXT(player_name, action_desc) 即可;若对中文分词要求高,更推荐把日志导出到 Elasticsearch 做检索——毕竟游戏日志本身是写多读少场景,数据库不该承担复杂搜索职责。
真正容易被忽略的是:哪怕你用的是 MySQL 8.0,默认建表语句没显式指定 ENGINE=InnoDB,它确实会自动选 InnoDB;但老项目迁移过来的表,SHOW TABLE STATUS LIKE 'game_log' 查出来的 Engine 字段很可能还是 MyISAM——这种历史包袱不主动扫一遍,问题总在凌晨三点爆发。











