mysql中的写入性能优化与高并发支持

批量插入性能远超单条INSERT,关键在于合理划分事务边界、禁用约束检查、使用LOAD DATA INFILE、规避自增主键热点、优化连接池配置,并优先排查锁与日志刷盘瓶颈。

mysql中的写入性能优化与高并发支持

批量插入比单条 INSERT 快得多,但要注意事务边界

单条 INSERT INTO t VALUES (1),(2) 和 1000 条 INSERT 语句在高并发下性能差距可达 10 倍以上。关键不是“能不能用批量”,而是“在哪切分事务”。
MySQL 的 autocommit=1 默认开启,每条 INSERT 都触发一次刷盘(innodb_flush_log_at_trx_commit=1 时),这是最大瓶颈。

  • INSERT INTO t VALUES (1),(2),(3),...,(1000) 替代循环执行 1000 次单值 INSERT
  • 显式开启事务:BEGIN; INSERT ... ; INSERT ... ; COMMIT;,把 100–1000 行包在一个事务里(太大易锁表、回滚开销高)
  • 临时调大 innodb_log_file_sizeinnodb_buffer_pool_size,避免频繁 checkpoint
  • 写入前禁用唯一索引和外键检查(仅限导入场景):SET unique_checks=0; SET foreign_key_checks=0;,完成后恢复

LOAD DATA INFILE 是最快写入方式,但权限和路径限制多

比等量 INSERT 快 5–20 倍,本质是绕过 SQL 解析层,直接走存储引擎接口。但它要求数据文件在 MySQL 服务端本地(或启用了 local_infile=ON 并配合客户端 --local-infile),且用户需有 FILE 权限。

  • 格式必须严格:字段分隔符(FIELDS TERMINATED BY ',')、行结束符(LINES TERMINATED BY '/n')、空值表示(NULL/N)都要匹配
  • 避免使用 REPLACEIGNORE,它们会触发行锁或唯一键扫描;如需去重,先写临时表再 INSERT ... SELECT ... ON DUPLICATE KEY UPDATE
  • 大文件分片导入更稳:split -l 100000 data.csv chunk_,再逐个 LOAD DATA INFILE '/path/chunk_aa'
  • 导入后立刻执行 ANALYZE TABLE t,更新统计信息,避免后续查询执行计划劣化

高并发写入时,自增主键冲突和热点页争用要主动规避

InnoDB 的聚簇索引让主键成为写入热点。若所有连接都往同一数据页末尾插入(比如 AUTO_INCREMENT 主键),会产生 LOCK_MODE_X 行锁竞争,甚至 adaptive hash index 锁等待。

云网OA

云网OA

采用JSP开发的办公自动化产品、基于B/S结构,运行环境:JDK v1.5、Tomcat v5.5、MySQL v4.1,三者均为以上版本其他相关内容:可视化流程设计: 流程支持串签、会签和分支流程,可以设置流程节点的修改、删除权限,并可指定流程中各个用户在表单中可以填写的域。智能表单所见即所得设计: 智能设计,自动在数据库中生成表格,方便优化程序 公共交流: 集论坛、博客、聊天室于一体文件柜:C

下载

  • innodb_autoinc_lock_mode=2(交错模式),允许并发获取自增值(需 binlog_format=ROW)
  • 避免 REPLACE INTOINSERT ... ON DUPLICATE KEY UPDATE 在高频写入场景滥用——它们先查后写,容易锁住唯一索引项
  • 考虑用 UUID_SHORT() 或雪花 ID(应用层生成)替代 AUTO_INCREMENT,但注意 UUID 无序性会导致二级索引碎片,需定期 OPTIMIZE TABLE
  • 写多读少场景可加 innodb_change_buffering=inserts(默认已开),延迟合并非唯一二级索引变更,降低随机 IO

连接池配置不当会让优化全失效

哪怕 SQL 和参数全调优了,如果应用层用短连接(每次请求新建/销毁连接),或连接池最大数设成 1000,照样卡在 Creating sort indexWaiting for table metadata lock

  • 连接池 maxActive / maxPoolSize 不应盲目设高;建议按实际并发请求数 × 1.5 设(如 QPS 200,平均响应 100ms,则活跃连接约 20)
  • 务必启用 wait_timeoutinteractive_timeout(建议 300 秒),防止空闲连接长期占着不放
  • SHOW PROCESSLIST 查看是否有大量 Sleep 状态连接;用 performance_schema.events_statements_summary_by_digest 找出慢写入的 SQL 模板
  • 写入类请求尽量走专用连接池(和读库分离),避免慢写拖垮读响应

真正卡住高并发写的,往往不是磁盘或 CPU,而是锁等待、日志刷盘节奏、或者连接没被复用。调参前先看 SHOW ENGINE INNODB STATUS/G 里的 SEMAPHORESTRANSACTIONS 部分,比盲目改 innodb_buffer_pool_size 有用得多。

https://www.php.cn/faq/2004664.html

发表回复

Your email address will not be published. Required fields are marked *