应使用DELETE WHERE配合时间条件清理,而非TRUNCATE或存储过程;必须为created_at字段建立索引,大表需分批(如LIMIT 5000)并加SLEEP限流,避免锁表与主从延迟。

MySQL中用DELETE + WHERE清理过期日志数据最直接
直接删比归档更常见,尤其日志表没外键依赖、没高并发写入时。DELETE FROM log_table WHERE created_at 是最常用写法。注意别漏加索引——<code>created_at 字段必须有索引,否则全表扫描会锁表几秒甚至几分钟。如果表超千万行,建议拆成小批量删:DELETE FROM log_table WHERE created_at ,循环执行直到影响行为 0。
避免在主库高峰期执行大DELETE
大DELETE会持有行锁+间隙锁,可能阻塞后续 INSERT/UPDATE。线上环境务必避开业务高峰;更稳妥的做法是把清理逻辑放到从库(只读)上跑完再同步到主库,或用 pt-archiver 工具分批迁移+删除,它自带休眠和限流。另外,autocommit=1 下每个 DELETE 都是独立事务,但大量小事务仍会刷盘频繁,可临时设 SET autocommit = 0 + 手动 COMMIT 控制提交节奏(需评估崩溃风险)。
用事件调度器(EVENT)自动触发清理任务
MySQL原生支持定时任务,比外部脚本更轻量。先确认 event_scheduler 已开启:SHOW VARIABLES LIKE 'event_scheduler',若为 OFF,需在配置文件加 event_scheduler = ON 或运行 SET GLOBAL event_scheduler = ON。然后建事件:
CREATE EVENT cleanup_old_logs<br>ON SCHEDULE EVERY 1 DAY<br>DO DELETE FROM log_table WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY) LIMIT 10000;注意:事件默认在定义者权限下运行,确保该用户有对应表的
DELETE 权限;且 LIMIT 必须显式写出,否则单次可能删太多。
分区表对超大日志表更高效
如果日志表年数据量超亿级,按月或按天分区后,DROP PARTITION 比 DELETE 快得多,本质是删文件而非逐行标记。例如按 created_at RANGE 分区,每月一个分区,清理只需 ALTER TABLE log_table DROP PARTITION p_2023_12。但分区维护成本高:新增分区要提前建好,否则插入会失败;且 WHERE 条件必须包含分区键才能裁剪,否则照样扫全分区。别为了清理而强行分区——小表加索引+分批删,比分区更简单可靠。


















