You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:43:17