對比 LONGTEXT 方案,LONGBLOB + mysql_stmt_send_long_data 以二進制協議分片傳輸,無需轉義、內存峰值僅為分片大小,是大文件入庫的正規軍姿勢。
CREATE DATABASE test;
USE test;
CREATE TABLE bintest (
id INT AUTO_INCREMENT PRIMARY KEY,
data LONGBLOB
) ENGINE=InnoDB;
mysql_stmt_init() → mysql_stmt_prepare() 準備 INSERT INTO bintest(data) VALUES(?)。MYSQL_BIND 綁定參數:buffer_type=MYSQL_TYPE_BLOB,length 指向 unsigned long 變量。mysql_stmt_bind_param() 綁定。mysql_stmt_send_long_data(stmt, 0, chunk_ptr, chunk_len) 發送數據片段(可多次調用)。mysql_stmt_execute() 執行寫入。MYSQL_STMT *stmt = mysql_stmt_init(mysql);
mysql_stmt_prepare(stmt, "INSERT INTO bintest(data) VALUES(?)", ...);
MYSQL_BIND bind[1] = {0};
bind[0].buffer_type = MYSQL_TYPE_BLOB;
bind[0].buffer = chunk_buf;
bind[0].length = &chunk_len;
bind[0].is_null = 0;
mysql_stmt_bind_param(stmt, bind);
while (bytes_read = fread(chunk_buf, 1, CHUNK_SIZE, fp)) {
mysql_stmt_send_long_data(stmt, 0, chunk_buf, bytes_read);
}
mysql_stmt_execute(stmt);
[mysqld]
max_allowed_packet = 1024M
innodb_log_file_size = 256M -- 大事務需大 redo log
修改 innodb_log_file_size 需停庫、刪除 ib_logfile*、重啟。
| 維度 | LONGTEXT + escape | LONGBLOB + stmt |
|---|---|---|
| 內存峰值 | 2×文件大小 | 分片大小(如 1MB) |
| CPU 開銷 | 轉義/反轉義 | 零拷貝二進制 |
| SQL 注入風險 | 理論存在 | 參數化天然免疫 |
| 代碼複雜度 | 低 | 中 |
innodb_flush_log_at_trx_commit=2 降低刷盤壓力(可接受 1s 數據丟失)。bintest 僅存純二進制。