C++批量执行MariaDB多语句INSERT仅前几次生效的问题排查
问题分析与解决
核心原因
当使用CLIENT_MULTI_STATEMENTS标志执行多条SQL语句时,必须遍历并处理所有返回的结果集,否则数据库连接会处于阻塞状态,后续的查询请求无法被服务器处理,表现为程序无响应。
你的代码中,每次执行拼接后的多条INSERT语句后,只调用了mysql_query,但没有处理每个INSERT对应的结果(即使INSERT没有返回行数据,也会返回影响行数的结果),导致连接被挂起,后续请求无法正常发送。
修复方案
在执行mysql_query后,循环调用mysql_next_result处理所有结果集,直到没有更多结果为止。同时建议添加错误检查,方便排查问题。
修改后的代码如下:
#include <windows.h> #include <iostream> #include <string> #include <format> #include "mysql/mysql.h" const char* user = "root"; const char* passwd = "password"; const char* host = "127.0.0.1"; const char* db; // = "data"; int port = 3306; MYSQL conn; int main() { mysql_init(&conn); if (!mysql_real_connect(&conn, host, user, passwd, NULL, port, NULL, CLIENT_MULTI_STATEMENTS)) { std::cerr << "连接失败: " << mysql_error(&conn) << std::endl; return 1; } if (mysql_select_db(&conn, "2024_04") != 0) { std::cerr << "选择数据库失败: " << mysql_error(&conn) << std::endl; mysql_close(&conn); return 1; } int odr1 = 0; int odr2 = 1; std::string str_concat = ""; while (true) { std::string str_queryInsert1 = std::format("INSERT INTO tb (odr1, odr2) values( {}, {})", odr1, odr1); std::string str_queryInsert2 = std::format("INSERT INTO tb (odr1, odr2) values( {}, {})", odr2, odr2); str_concat.append(str_queryInsert1); str_concat.append(";"); str_concat.append(str_queryInsert2); str_concat.append(";"); odr1 += 1; odr2 += 1; if ((odr1 % 4) == 0) { int res = mysql_query(&conn, str_concat.c_str()); if (res != 0) { std::cerr << "查询执行失败: " << mysql_error(&conn) << std::endl; mysql_close(&conn); return 1; } // 处理所有结果集,释放资源 do { MYSQL_RES* result = mysql_store_result(&conn); if (result != NULL) { mysql_free_result(result); } if (mysql_next_result(&conn) > 0) { std::cerr << "处理结果集失败: " << mysql_error(&conn) << std::endl; mysql_close(&conn); return 1; } } while (mysql_more_results(&conn)); Sleep(1000); str_concat.clear(); std::cout << "SENT" << std::endl; } } mysql_close(&conn); return 0; }
额外优化建议
- 使用预处理语句:避免手动拼接SQL,既可以防止SQL注入,也能提升批量插入效率,无需处理多语句结果集问题。示例片段:
MYSQL_STMT* stmt = mysql_stmt_init(&conn); const char* insert_sql = "INSERT INTO tb (odr1, odr2) VALUES (?, ?)"; if (mysql_stmt_prepare(stmt, insert_sql, strlen(insert_sql)) != 0) { std::cerr << "预处理语句失败: " << mysql_error(&conn) << std::endl; return 1; } MYSQL_BIND bind[2]; memset(bind, 0, sizeof(bind)); int odr_val1, odr_val2; bind[0].buffer_type = MYSQL_TYPE_LONG; bind[0].buffer = &odr_val1; bind[1].buffer_type = MYSQL_TYPE_LONG; bind[1].buffer = &odr_val2; mysql_stmt_bind_param(stmt, bind); while(true) { odr_val1 = odr1; odr_val2 = odr1; mysql_stmt_execute(stmt); odr_val1 = odr2; odr_val2 = odr2; mysql_stmt_execute(stmt); odr1 +=1; odr2 +=1; if((odr1%4)==0) { Sleep(1000); std::cout << "SENT" << std::endl; } }
- 完善错误检查:原代码未检查连接、选库、查询的返回值,出现错误时无法及时定位问题。
- 简化变量定义:原代码中
connection指针未实际使用,可删除以简化代码。
内容的提问来源于stack exchange,提问作者maynull
相关产品推荐
相关产品推荐

