mysql并发写入日志表如何优化_mysql高频写入方案

来源:这里教程网 时间:2026-02-28 20:40:39 作者:

INSERT DELAYED
还是直接放弃?

MySQL 5.6 及以后版本已彻底移除

INSERT DELAYED
,强行使用会报错
ERROR 1064 (42000)
。它原本只适用于
MyISAM
表,且在高并发下实际延迟不可控、丢失风险高,现在连语法都不支持了。别查旧教程,直接跳过。

日志表必须用
ENGINE=InnoDB
吗?

不一定。如果日志表只写不读、不依赖事务、不需崩溃恢复,

ENGINE=MyISAM
或更优的
ENGINE=ROCKSDB
(需启用 MyRocks)反而吞吐更高。但注意:
MyISAM
写入时整表锁,若混杂
SELECT
查询会严重阻塞;而
InnoDB
的行锁 + 插入缓冲(
innodb_change_buffer
)对主键/索引外的写入更友好。

纯追加写 + 零查询 →
MyISAM
(简单场景可测)或
ROCKSDB
有定时归档/查询需求 →
InnoDB
,关掉非必要索引(尤其是
TEXT
字段上的全文索引)
务必禁用
innodb_flush_log_at_trx_commit=2
(牺牲最多 1 秒数据持久性换性能),并调大
innodb_log_file_size

INSERT ... VALUES (),(),()
批量写比单条快多少?

实测 100 条批量写入比 100 次单条快 5–15 倍,取决于网络往返和事务开销。但别盲目堆到 10000 条:MySQL 默认

max_allowed_packet
通常为 4MB,超限会报
ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes

INSERT INTO log_table (ts, level, msg) VALUES
(NOW(), 'INFO', 'user login'),
(NOW(), 'WARN', 'slow query detected'),
(NOW(), 'ERROR', 'db timeout');
每批控制在 100–500 行(视单行大小调整) 显式开启事务:
BEGIN; INSERT ...; COMMIT;
,避免自动提交开销
应用层做缓冲:内存队列积攒 N 条再刷库,比数据库层优化更可控

分区表能扛住每秒上千写入吗?

按时间分区(如

PARTITION BY RANGE (TO_DAYS(ts))
)对写入性能几乎无提升,反而增加优化器负担;但对后续按月归档、
DROP PARTITION
清理极有用。真正起效的是「分表」——比如按天生成
log_20240501
log_20240502
,用应用路由写入,彻底规避锁争用和 B+ 树分裂压力。

不要用 MySQL 自动分区应对高写,那是给查询设计的 分表后每个表独立
auto_increment
、独立缓冲池,写入完全隔离
务必在应用层维护表名映射,避免跨表查询(日志本来就不该频繁跨天查) 分表和批量事务是见效最快的两个动作,但最容易被忽略的是:**日志字段类型是否最小化**。用
TINYINT
存 level 而不是
VARCHAR(10)
,用
INT UNSIGNED
存 user_id 而非
BIGINT
,单行省 10 字节,每秒 2000 写入就是 20KB/s 的 I/O 节省——这比调参实在得多。

相关推荐