mysql 出现 Commands out of sync; you can't run this command now

存储过程中就只有一句普通的select * from ...;
第一次调用成功,
然后mysql_stmt_close()..
再调一次,结果mysql_stmt_prepare()这一句,就出现CR_COMMANDS_OUT_OF_SYNC错误。
郁闷啊。。。 
------Solutions------
你的代码是什么? 
------Solutions------
void test() 
{     
//...
       int t1,t2;

       MYSQL_STMT *hStmt = mysql_stmt_init(m_hSql);
char sql[] = "call test(?)";
if ( mysql_stmt_prepare( hStmt,sql,static_cast<unsigned long>(strlen(sql))) != 0 )
    printf(mysql_stmt_error(hStmt);

ibind.buffer_type = MYSQL_TYPE_LONG;
ibind.buffer = t1;

if ( mysql_stmt_bind_param(hStmt,&ibind) != 0 )
     printf(mysql_stmt_error(hStmt));

if ( mysql_stmt_execute(hStmt) != 0 )
         printf(mysql_stmt_error(hStmt));

obind.buffer_type= MYSQL_TYPE_LONG;
obind.buffer= (char *)&t2;

       if (mysql_stmt_bind_result(hStmt, &obind) !=0 )
printf(mysql_stmt_error(hStmt));

if (mysql_stmt_store_result(hStmt) !=0 )
printf(mysql_stmt_error(hStmt)); 

        rows = mysql_stmt_num_rows(hStmt);
for( my_ulonglong i=0; i<rows; ++i )
{
     nRet = mysql_stmt_fetch(hStmt);
             //...
         }
        mysql_stmt_close(hStmt);
}

//存储过程
CREATE DEFINER=`root`@`localhost` PROCEDURE test( in t1 int)
BEGIN
   select t2 from test from id=t1;
END

如果test()连着调两次,就会报错




------Solutions------
if ( mysql_stmt_execute(hStmt) != 0 )
  printf(mysql_stmt_error(hStmt));
 
在正确执行后,要释放这个预处理。

DEALLOCATE PREPARE hStmt;

------Solutions------
直接调用sql code释放?
hStmt是在c中的句柄呀,有对应的c api函数吗? 
------Solutions------
mysql_stmt_close已经足够了。
问题不在这儿,而是中间的调用顺序出了问题:
应该是:
1. stmt_bind_param
2. stmt_execute
3. stmt_store_result
4. stmt_bind_result
5. stmt_close

你先按这个顺序处理一遍试试吧。

------Solutions------
顺序是对的,第二次再调用这个函数的时候,mysql_stmt_prepare这里就出错了。
如果不是调用存储过程"call test(?)"的话,直接调用用"select t2 from test from id=?"命令的话,没有发现问题。 
------Solutions------
你的mysql版本是多少?我可以拿到本地来试一下。

从错误来看,是由于函数调用顺序不当造成的。 
------Solutions------
我在本地试了一下,使用的是版本:mysql-5.1.26-rc-win32。
你的代码有一个地方确实有问题。
这可能也需要我们总结一下。
1. 使用存储过程call test(?)返回结果集,需要创建CLIENT_MULTI_STATEMENTS的客户端连接
2. 在两次调用call test(?),要释放中间产生的若干结果集。

具体做法如下:
在mysql_stmt_close之前,最好调用一次:mysql_stmt_free_result(hStmt);
在mysql_stmt_close()调用完以后,立即使用如下循环释放其它我们不需要的MYSQL_RESULT:
    do
    {
        MYSQL_RES* res = mysql_store_result(mysql_);
          mysql_free_result(res);
    }
    while ( (0 == mysql_next_result(mysql_)) );

如果没有这一段释放,连续调用,则会出现楼主所说的错误。

总之,调用存储过程产生结果集跟调用select查询产生结果集,还是有一些不一样。
前者可能产生多个结果集。



------Solutions------
很感谢iihero,我使用的是5.5.3版。
使用mysql_stmt_free_result(hStmt);没有什么作用。
不过:
do
  {
  MYSQL_RES* res = mysql_store_result(mysql_);
  mysql_free_result(res);
  }
  while ( (0 == mysql_next_result(mysql_)) );

确实能解决问题,呵呵!
留下个疑问,这样一个连接就无法让多线程共享数据了,因为无法确定多线程是否安全。 
------Solutions------
引用 9 楼 ldhhp2003 的回复:
很感谢iihero,我使用的是5.5.3版。
使用mysql_stmt_free_result(hStmt);没有什么作用。
不过:
do
  {
  MYSQL_RES* res = mysql_store_result(mysql_);
  mysql_free_result(res);
  }
  while ( (0 == mysql_next_result(mysql_)) );

确实能解决问题,呵呵!
留下个疑问,这样一个连接就无法让多线程共享数据了,因为无法确定多线程是否安全。


你的版本很新啊,呵呵。我来不及更新版本。
前边的free_result是调用惯用法。意即在close之前,进行free,释放掉不必要的cursor之类的东东。后边的while是必须的。
一个连接当然不能多线程共享了。
可以每线程一个单独的连接进行处理。多线程共享连接,那么中间产生的许多资源就成了共享资源了,需要进行锁定,处理极为不便。



------Solutions------
这种做法解决了问题,不过或许可以算是预处理函数的一种bug,按常理mysql_stmt_close()或者mysql_stmt_free_result()应该会自动释放掉产生的资源,只是没想到还要使用非预处理函数来处理相关的资源。
至于多个线程用同一个连接,手册上也介绍了相关介绍,可以使用,不过要自行加锁处理。复杂度也就更高了。

------Solutions------
引用 11 楼 ldhhp2003 的回复:
至于多个线程用同一个连接,手册上也介绍了相关介绍,可以使用,不过要自行加锁处理。复杂度也就更高了。


确实如此。 
------Solutions------
问题解决了,可以结帖了。

MYSQLCommands out of sync; you can't run this command now

04-21

昨天请高人帮忙改了个存储过程,也觉得代码已经没问题了,但跑起来总是提示这个错误,头都大了。rnrn存储过程代码如下:rn[code=SQL]rn-- --------------------------------------------------------------------------------rn-- Routine DDLrn-- --------------------------------------------------------------------------------rnDELIMITER $$rnrnCREATE DEFINER=`root`@`%` PROCEDURE `USP_CreateTrackerLogTable`(IN Pointer DATETIME,IN Counts INT)rnbeginrn declare CountPointer int;rn declare DateString varchar(20);rn declare TableName varchar(50);rn declare SQLTxt varchar(5000);rn declare ExecuteSQL varchar(8000);rn rn Set CountPointer = Counts;rn rn Set SQLTxt = ' rn CREATE TABLE IF NOT EXISTS Tracker_Log(rn LogID bigint PRIMARY KEY auto_increment NOT NULL, /*自增ID*/rn TrackerID varchar(50) NOT NULL, /*日志ID*/rn LogTime datetime NOT NULL, /*日志时间*/rn SessionId varchar(50) NOT NULL, /*会话ID*/rn PassportID bigint NULL, /*账户ID*/rn UserID bigint NULL, /*用户ID*/rn ClientIP varchar(64) NULL, /*客户端IP*/rn ServerIP varchar(64) NULL, /*应用服务器IP*/rn CurrentUrl varchar(255) NULL, /*当前页链接*/rn ReferrerUrl varchar(255) NULL, /*前一页链接*/rn ClickLinkUrl varchar(255) NULL, /*超链接链接地址*/rn ClickLinkTitle nvarchar(200) NULL, /*超链接链接名*/rn CurrentClientTime datetime NULL, /*当前客户端时间*/rn CurrentServerTime datetime NULL, /*当前应用服务器时间*/rn ClientServerTimeDif bigint Null, /*客户端与服务器时间差*/rn ServerExecuteTime bigint NULL, /*应用服务器执行请求时间*/rn NetTransTime bigint NULL, /*网络传输时间*/rn ServerResponseTime datetime NULL, /*服务器输出时时间*/rn ClientLoadTime bigint NULL, /*客户端页面加载时间*/rn UserDwellTime bigint NULL /*用户在当前页停留时间*/rn );';rnrn WHILE (CountPointer > 0) DOrn BEGINrn /*处理日期*/rn SET DateString = CONCAT(RIGHT(CAST(YEAR(Pointer) AS CHAR(4)), 2),'_',rn RIGHT('0' + CAST(MONTH(Pointer) AS CHAR(2)), 2),'_',rn RIGHT('0' + CAST(DAY(Pointer) AS CHAR(2)), 2));rn rn Set TableName = 'Tracker_Log_' + DateString;rn rn /*替换脚本字符串*/rn Select ExecuteSQL = Replace(SQLTxt, 'Tracker_Log', TableName);rnrn /*执行*/rn Select SQLTxt;rn /*SET @asql=ExecuteSQL;rn PREPARE tt FROM @asql;rn EXECUTE tt;*/rn /*print ExecuteSQL*/rn rn /*准备下一次*/rn Set CountPointer = CountPointer - 1;rn SET Pointer = DATE_ADD(CURDATE(), INTERVAL CountPointer DAY );rn END;rn END WHILE;rnENDrnrn[/code]rnrnrn另外,我可能要在SQLTxt中放入创建多个表的代码,用于定时任务,不知道是否也行?rn因为现在一个表我都跑不过去,多个表一起创建就没有测试,特请教大家。

没有更多推荐了,返回首页