INSERT 是最常用的 DML 操作,但高並發寫入場景下性能差異可達數十倍。本文系統梳理語法變體、批量寫入技巧、事務邊界控制、InnoDB 關鍵參數調優,助你構建高吞吐寫入鏈路。
-- 1. 標準插入(指定列,防止表結構變更導致錯誤) INSERT INTO `table` (col1, col2, col3) VALUES (val1, val2, val3); -- 2. 多行單語句插入(核心優化手段,減少網絡往返與解析開銷) INSERT INTO `table` (col1, col2) VALUES (val1, val2), (val3, val4), (val5, val6); -- 3. INSERT ... SELECT(表間數據遷移/複製) INSERT INTO target_table (col1, col2) SELECT col1, col2 FROM source_table WHERE condition; -- 4. INSERT IGNORE / ON DUPLICATE KEY UPDATE(冲突處理) INSERT INTO `table` (id, val) VALUES (1, 'a') ON DUPLICATE KEY UPDATE val=VALUES(val);
<?php
$conn = new mysqli('localhost', 'root', 'pass', 'db');
$stmt = $conn->prepare("INSERT INTO runoob_tbl (title, author, date) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $title, $author, $date);
// 循環綁定執行...
$stmt->close();
$conn->close();
?>
原理:減少客戶端-服務端網絡往返(RTT)、SQL 解析優化器開銷、Binlog 組提交頻率。
-- 差:循環執行 10000 次 INSERT(耗時 ~10s+) -- 優:單條 INSERT 包含 10000 行 VALUES(耗時 ~0.5s) -- 注意:max_allowed_packet 默認 4MB/1MB,超大批次需調大或分批
START TRANSACTION; INSERT ...; INSERT ...; ... (批量) COMMIT; -- 原理:將多次 fsync 合併為一次,利用 redo log 組提交(group commit) -- 注意:事務過大超過 innodb_log_buffer_size 會導致頻繁刷盤,反而變慢。建議每 1000-5000 行提交一次。
| 參數 | 推薦值 | 作用 | 調優邏輯 |
|---|---|---|---|
| innodb_buffer_pool_size | 物理內存 70-80% | 緩存數據+索引+鎖+插入緩衝 | 核心參數,越大寫入越快(減少磁盤 IO) |
| innodb_log_file_size | 512M - 2G | Redo log 文件大小 | 大文件減少 checkpoint 頻率,寫入更平滑 |
| innodb_log_buffer_size | 16M - 64M | 事務日志緩衝 | 大事務/大 Blob 需調大,避免提交前刷盤 |
| innodb_flush_log_at_trx_commit | 2 (高性能) / 1 (高安全) | 提交時刷盤策略 | 2=寫 OS 緩存由 OS 刷盤,性能提升 5-10 倍,極端斷電丟 1 秒數據 |
| innodb_flush_method | O_DIRECT | 避免雙重緩存 | 繞過 OS 頁緩存,直接寫磁盤,減少 CPU 佔用 |
| innodb_io_capacity | SSD: 5000-20000 | 後台刷頁能力 | 根據磁盤 IOPS 設置,防止刷頁跟不上 |
場景:插入 100 萬行,每行 5 列,SSD 雲盤,16C32G 實例 -------------------------------------------------------------- 單條自動提交 | ~2,000 rows/sec | 基準 批量 1000 行/語句 | ~15,000 rows/sec | 7.5x 批量 1000 行 + 事務 | ~45,000 rows/sec | 22x 批量 1000 行 + 事務 + 參數調優 (flush_log=2, buffer_pool=20G) | ~120,000 rows/sec | 60x
Packet too large,動態調整 SET GLOBAL max_allowed_packet=64M; 或分批。VALUES 批量插入(每批 1000-5000 行)。buffer_pool 足夠大、log_file_size ≥ 1G、flush_log_at_trx_commit=2(可接受秒級丟失)。Innodb_log_waits、Innodb_buffer_pool_wait_free 為 0。掌握這些,寫入性能不再是瓶頸。