VC重复调用mysql查询接口出现Commands out of sync的解决方案:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <cstring>
#include <string.h>
#include <atltime.h>
#include <afxdisp.h>
using namespace std;
char* OutErrors(MYSQL* pMySql)
{
return const_cast<char *>(mysql_error(pMySql));
}
int main(int argc, char* argv[])
{
try
{
//初始化数据
MYSQL *pMySql = mysql_init((MYSQL*)NULL);
if (pMySql != NULL)
{
//创建连接
if (mysql_real_connect(pMySql,"ip","user","pass","dbname",3306,NULL,CLIENT_MULTI_STATEMENTS))
{
mysql_set_character_set(pMySql,"gb2312");
for(int i=0; i<5; i++)
{
int nvalue = mysql_real_query(pMySql,"call P_SUPPLIER_LOGIN_T('fuxiongjunzlj','3d641b2e4f5dc2b1fb0ab3dff6bc8d92')",(unsigned int)strlen("call P_SUPPLIER_LOGIN_T('fuxiongjunzlj','3d641b2e4f5dc2b1fb0ab3dff6bc8d92')"));
//int nvalue = mysql_real_query(pMySql,"SELECT * FROM cmsadvice",(unsigned int)strlen("SELECT * FROM cmsadvice"));
if(nvalue == 0)
{
MYSQL_RES *myquery = NULL;
myquery = mysql_store_result(pMySql);
MYSQL_FIELD *field;
//获取字节大小
int FileNumber = mysql_num_fields(myquery);
//获取返回名称
for(int j=0; j<FileNumber; j++)
{
field = mysql_fetch_field_direct(myquery,j);
printf("Field %u is %s \t", j, field->name);
}
printf("\n");
//获取返回值
MYSQL_ROW record;
while(record = mysql_fetch_row(myquery))
{
for(int k=0; k<FileNumber; k++)
{
printf("[%s] \t", record[k]);
}
}
printf("\n");
mysql_free_result(myquery);//标记1
while ((mysql_next_result(pMySql)) != 0)//在这里加一个循环即可解决无法重复调用的问题 标记2
{
mysql_free_result(myquery);
}
printf("查询成功... \n");
}
else
{
printf("查询异常:%s \n",OutErrors(pMySql));
}
}
}
else
{
//输出异常信息
OutErrors(pMySql);
return false;
}
}
}
catch(...)
{
return 0;
}
}
也就是标记1的地方正常释放但有可能在释放的时候存储过程返回的记录集有可能没有完成 当使用当前连接进行下一次调用存储过程时mysql内部的处理是自动pass掉的,也是情有可原的.知道这里的原因,增加标记2处的处理即可解决问题其实我们一般只用mysql_query、mysql_use_result等几个函数,问题的症结在于当执行一个存储过程的时候, 数据库返回的是多个数据集合,即使只有一个数据集合,他也会有一个空集合用于结束一次回话,作者骂他变态,其实不然,可能作者考虑到的只是一般的请 求,mysql是给所有用户使用的,说不能真有变态的人把图片文件等等直接保存在mysql字段里面,那么回复就不可能一次完成,需要多此网络交互,那么 所有的交互肯定需要一个结束符号,并且存储过程本来就可以返回多个数据集合,如果他在c pai中只做一个结果己处理就允许下一次全新的请求,那么对于同一连接,在mysql服务断其实还有没有发送完成的数据,这个时候他安全的做法就是不接受 任何新的请求,直到数据发送完全,或者连接关闭,不然,mysql协议解析就会出现问题,下次发送就会出现黏包或者丢包,所以他的做法是完全正确的,即使 只有一个结果集合,也需要当前会话内的通讯(比如mysql_next_result)确认完毕,然后结束本次请求,这个时候服务端其实没有数据了,但是 这个过程是不能省略的,然后在不关闭连接的情况下就可以进行全新的请求了。
所以总结起来就是:使用存储过程的时候一定要循环执行,把所有的结果集合都取到,直到为空,这个时候当前数据库连接才可以安全归还回去.
参考文章:http://www.jb51.net/article/27085.htm