您的位置:首页 > 数据库 > MySQL

Mysql问题一则:Commands out of sync

2017-10-22 15:35 204 查看
最近在使用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的错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐