Recently, when using C++ to access MySQL (using the C API provided by mysql), an occasional error occurs:
Commands out of sync; you can't run this command now
Errors are explained in the Mysql document:
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.
When query is executed, mysql places the result set in a result set. There are two reasons for the above problems:
First, a new query is executed before releasing the object referred to by MYSQL_RES (using mysql_free_result()).
The second is to execute two queries that return results without calling mysql_use_result() or mysql_store_result() to extract the result set.
MySQL communicates with the client using a "half-duplex" reply protocol. For each query sent by the client, the server "forcibly pushes" the result to the client. The client needs to execute mysql_use_result() or mysql_store_result() to retrieve the result from the server. This is a complete query interaction. Only submitting the query without retrieving the result will lead to Commands out of sync. .
Therefore, for query statements with returned results, the following processing is required:
TC_Mysql::MysqlData TC_Mysql::queryRecord(const string& sSql)
{
MysqlData data;
/**
Not connected, connected to the database
*/
if(!_bConnected)
{
connect();
}
_sLastSql = sSql;
int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
if(iRet != 0)
{
/**
Automatic reconnection
*/
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)));
}
// Save the result set
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);
}
// Release result set
mysql_free_result(pstRes);
return data;
}
For queries that do not need to return results, the number of records affected by the query is obtained by mysql_affected_rows(_pstMql).
For multi-threaded cases, ensure that each thread accesses the database using a separate Mysql. Otherwise, thread 1 may not save the result set, and thread 2 will initiate a new query, which will result in a Commands out of sync error.