已采纳
回答正文
回复
讨论正文
该问题的正文、回答与讨论。
背景
8 年数据工程,目前负责一个实时 ETL 管道。峰值 10 个写入线程并行写 MySQL 8.0.36(8C32G,NVMe SSD,同机部署),每线程每批 5000 行 INSERT,commit 间隔约 50-100ms,整体写入约 50k rows/s。
现象
SHOW ENGINE INNODB STATUS 无 lock wait、无 deadlocks,行锁和表锁等待时间均为 0;performance_schema.events_waits_summary_global_by_event_name 里 wait/io/file/innodb/innodb_log_file 的 SUM_TIMER_WAIT 在飙升时段明显增大;已尝试的排查与结果
innodb_flush_log_at_trx_commit=1(默认值)→ 问题稳定复现;=2 → commit P99 降到 200ms 以内,但业务不能接受 1s 级别的 crash loss,必须回滚;innodb_log_buffer_size 从默认 16MB 调到 128MB → 无明显改善(预期之内,瓶颈不在 buffer 容量);innodb_flush_method 已确认是 O_DIRECT,排除了 OS page cache 刷盘干扰;iostat -x 1 显示飙升时段 %util 从 5% 跳到 40%、await 从 0.1ms 跳到 3ms,说明确实有额外的物理 IO 发生,但不确定是 group commit 凑批后的一次大 fsync 还是日志段切换;期望得到的答案形态
SHOW ENGINE INNODB STATUS 的 LOG 段和 performance_schema,没找到现成的,难道只能靠 perf + eBPF 抓 fsync 调用栈?)innodb_flush_log_at_trx_commit=2 的 crash loss,还有什么手段能降低 commit P99?比如应用层攒批(把 10 线程的 commit 节奏对齐到同一个 tick)、调整 innodb_log_file_size(8.0.30+ 的 innodb_redo_log_capacity)增大日志段减少切换、或者用 XA 2PC 把多表 commit 合并?innodb_redo_log_capacity / innodb_log_file_size 一般设多大?有没有跟写入吞吐挂钩的经验公式或上限?参考