Mysql问题一则:Commands out of sync

最近在使用C++访问mysql(使用mysql提供的C API)时,偶尔会出现一个错误:

Commands out of sync; you can’t run this command now

Mysql文档中说明错误:

Commands out of sync
If you get “Commands out of sync; you can’t run this command now” in your client code, you are calling client functions in the wrong order.
This can happen, for example, if you are using mysql_use_result() and try to execute a new query before you have called mysql_free_result(). It can also happen if you try to execute two queries that return data without calling mysql_use_result() or mysql_store_result() in between.

当执行完query后,mysql将结果集放在一个result集中,产生以上问题的原因有两个:
一是在将MYSQL_RES所指对象释放(使用mysql_free_result())之前,执行了一个新的query;
二是执行了两条会返回结果的query,两者之间没有调用mysql_use_result() 或者 mysql_store_result() 来将结果集取出来。

MySQL 和客户端通信使用的是“半双工”的应答协议,客户端每发送一个查询,服务器“强行推送”结果给客户端,客户端需要执行 mysql_use_result() 或 mysql_store_result() 从服务器端取回结果,这是一次完整的查询交互,只提交查询而不取回结果就会导致 Commands out of sync。

因此,对于有返回结果的查询语句,需要如下处理:


TC_Mysql::MysqlData TC_Mysql::queryRecord(const string& sSql)
{
    MysqlData   data;

    /**
    没有连上, 连接数据库
    */
    if(!_bConnected)
    {
        connect();
    }

    _sLastSql = sSql;

    int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
    if(iRet != 0)
    {
        /**
        自动重新连接
        */
        int iErrno = mysql_errno(_pstMql);
        if (iErrno == 2013 || iErrno == 2006)
        {
            connect();
            iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
        }
    }

    if (iRet != 0)
    {
        throw TC_Mysql_Exception("[TC_Mysql::execute]: mysql_query: [ " + sSql+" ] :" + string(mysql_error(_pstMql)));  
    }

    // 将结果集保存起来
    MYSQL_RES *pstRes = mysql_store_result(_pstMql);

    if(pstRes == NULL)
    {
        throw TC_Mysql_Exception("[TC_Mysql::queryRecord]: mysql_store_result: " + sSql + " : " + string(mysql_error(_pstMql)));
    }

    vector<string> vtFields;
    MYSQL_FIELD *field;
    while((field = mysql_fetch_field(pstRes)))
    {
         vtFields.push_back(field->name);
    }

    map<string, string> mpRow;
    MYSQL_ROW stRow;

    while((stRow = mysql_fetch_row(pstRes)) != (MYSQL_ROW)NULL)
    {
        mpRow.clear();
        unsigned long * lengths = mysql_fetch_lengths(pstRes);
        for(size_t i = 0; i < vtFields.size(); i++)
        {
            if(stRow[i])
            {
                mpRow[vtFields[i]] = string(stRow[i], lengths[i]);
            }
            else
            {
                mpRow[vtFields[i]] = "";
            }
        }

        data.data().push_back(mpRow);
    }

    // 释放结果集
    mysql_free_result(pstRes);

    return data;
}

对于不需要返回结果的查询,则通过mysql_affected_rows(_pstMql);来获取查询所影响的记录条数。

对于多线程的情况,则要保证每个线程使用独立的Mysql来对数据库进行访问,否则可能线程1还没将结果集保存起来,线程2便发起了新的查询,便会出现Commands out of sync的错误。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值