COMMIT出现在慢查询日志中,说明其执行时间超过long_query_time阈值,是独立慢操作而非附属动作;主因包括redo log与binlog刷盘、二进制日志轮换阻塞、磁盘IO过载等。

因为 COMMIT 本身可能耗时过长,超过 long_query_time 阈值,它就不是“附属动作”,而是一条独立的慢操作。
commit 出现在慢查询日志里,说明它真的慢了
很多人看到慢日志里只有 COMMIT,下意识觉得“这不算 SQL”,其实是误解。MySQL 把事务提交当作一个需要完整执行、同步刷盘、等待锁/日志落盘的原子操作。一旦它卡住,就会被记录——和 SELECT 或 UPDATE 没有本质区别。
-
COMMIT耗时主要来自:InnoDB redo log 刷盘(受innodb_flush_log_at_trx_commit控制)、binlog 写入与 fsync(受sync_binlog影响)、二进制日志轮换(max_binlog_size触发时会阻塞所有提交) - 磁盘 IO 过载时,
COMMIT等待刷盘的时间可能从几毫秒飙到数秒,轻松跨过默认 10 秒或业务设的 2 秒阈值 - 即使事务里只执行了一行
INSERT,只要提交阶段卡住,慢日志里就只记COMMIT——前面那句 INSERT 不会单独出现
为什么 mysqldumpslow 看不到真正的问题
mysqldumpslow 默认过滤掉非查询语句,COMMIT 就是典型被忽略项。它还会把不同事务的 COMMIT 合并成一条抽象统计,掩盖了“某类事务提交集中变慢”的信号。
- 用
pt-query-digest --filter '$event->{fingerprint} =~ /^COMMIT/i'才能单独拎出所有 commit 记录 - 查
Rows_examined字段没意义(commit 没这字段),但要看Lock_time和Query_time的差值:如果Query_time明显大于Lock_time,说明瓶颈在 IO 或日志同步,不是锁冲突 - 配合
SHOW ENGINE INNODB STATUS\G查TRANSACTIONS部分,看是否有大量事务停在flushing log或waiting for binlog to be written
怎么确认是不是 commit 真的慢,而不是日志误报
先排除配置和权限问题,再验证 commit 行为本身:
- 运行
SHOW VARIABLES LIKE 'slow_query_log',确保是ON;再查slow_query_log_file路径是否存在、MySQL 进程是否有写权限 - 检查
long_query_time实际值(注意:连接建立后该值即固化,新设置只对后续连接生效) - 临时开启
log_queries_not_using_indexes = OFF,避免无索引查询干扰判断 - 用
SELECT SLEEP(3)测试:如果这条语句进了慢日志,说明阈值和日志功能正常;再对比一个真实小事务BEGIN; INSERT ...; COMMIT;是否也进日志,就能确认 commit 是否真慢
真正难处理的是那种偶发性 commit 延迟——它不总发生,但每次出现都伴随业务超时。这时候不能只盯 SQL,得同时看磁盘 IOPS、binlog 文件大小、innodb_log_waits 状态值,以及是否刚好撞上 binlog rotate 时间点。这些细节往往比加索引更关键,却最容易被跳过。


















