Mysql++关于多数据集查询Commands out of sync; you can‘t run this command now的问题

4 篇文章 0 订阅

        今天在项目中使用了Mysql++调用Mysql的存储过程来实现功能,但是碰到一个有意思的问题,当成功调用存储过程后,再次做其他的查询,确返回Commands out of sync; you can't run this command now的错误。

        Query query = conn.query();
		memset(cSql, 0, sizeof(cSql));
		sprintf(cSql, "call %s('%s','0','1',@phoneno,@uuid,@projectid,@batchid,@companyid,@displaynum,@dialtype)", m_AutoPrcoName, strChan.GetBuffer(0));
		StoreQueryResult pResult = query.store(cSql, strlen(cSql));
		if (!pResult)
		{
			CallBack_LogReport(Input->nChan, 3, "AutoDialout_MultiCom error1\n");
			time(&m_ChanInfo[Input->nChan].LastNoDialoutTime);
			pthread_mutex_unlock(&m_DialoutMutex);
			return -1;
		}

		sprintf(cSql, "select @phoneno,@uuid,@projectid,@batchid,@companyid,@displaynum,@dialtype");
		pResult = query.store(cSql, strlen(cSql)); //此处出现问题
		if (!pResult)
		{
			CallBack_LogReport(Input->nChan, 3, "AutoDialout_MultiCom error2\n");
			time(&m_ChanInfo[Input->nChan].LastNoDialoutTime);
			pthread_mutex_unlock(&m_DialoutMutex);
			return -1;
		}

        查阅了官方的文档,其实对这个问题的描述还是很清晰的,而且专门用了一节,也给出了解决方案,现摘录如下(只有英文哦),其实关于就是在于对于返回多个数据集结果的查询,必须讲数据集结果取完,即使并没有什么用,否则就会报出Commands out of sync; you can't run this command now的错误。

3.16. Concurrent Queries on a Connection
An important limitation of the MySQL C API library — which MySQL++ is built atop, so it shares this limitation —
is that you can only have one query in progress on each connection to the database server. If you try to issue a second
query while one is still in progress, you get an obscure error message about “Commands out of sync” from the underlying
C API library. (You normally get this message in a MySQL++ exception unless you have exceptions disabled, in which
case you get a failure code and Connection::error() returns this message.)
There are lots of ways to run into this limitation:
• The easiest way is to try to use a single Connection object in a multithreaded program, with more than one thread
attempting to use it to issue queries. Unless you put in a lot of work to synchronize access, this is almost guaranteed
to fail at some point, giving the dread “Commands out of sync” error.
• You might then think to give each thread that issues queries its own Connection object. You can still run into
trouble if you pass the data you get from queries around to other threads. What can happen is that one of these child
objects indirectly calls back to the Connection at a time where it’s involved with another query. This is properly
covered elsewhere, in Section 7.4, “Sharing MySQL++ Data Structures”.)
• One way to run into this problem without using threads is with “use” queries, discussed above. If you don’t consume
all rows from a query before you issue another on that connection, you are effectively trying to have multiple
concurrent queries on a single connection. Here’s a recipie for this particular disaster:
UseQueryResult r1 = query.use("select garbage from plink where foobie='tamagotchi'");
UseQueryResult r2 = query.use("select blah from bonk where bletch='smurf'");
The second use() call fails because the first result set hasn’t been consumed yet.
• Still another way to run into this limitation is if you use MySQL’s multi-query feature. This lets you give multiple
queries in a single call, separated by semicolons, and get back the results for each query separately. If you issue
three queries using Query::store(), you only get back the first query’s results with that call, and then have to
call store_next() to get the subsequent query results. MySQL++ provides Query::more_results() so
you know whether you’re done, or need to call store_next() again. Until you reach the last result set, you can’t
issue another query on that connection.
• Finally, there’s a way to run into this that surprises almost everyone sooner or later: stored procedures. MySQL
normally returns at least two result sets for a stored procedure call. The simple case is that the stored procedure
contains a single SQL query, and it succeeds: you get two results, first the results of the embedded SQL query, and
then the result of the call itself. If there are multiple SQL queries within the stored procedure, you get more than
two result sets. Until you consume them all, you can’t start a new query on the connection. As above, you want to
have a loop calling more_results() and store_next() to work your way through all of the result sets
produced by the stored procedure call.

       按照文档的提示,修改代码如下:

        Query query = conn.query();
		memset(cSql, 0, sizeof(cSql));
		sprintf(cSql, "call %s('%s','0','1',@phoneno,@uuid,@projectid,@batchid,@companyid,@displaynum,@dialtype)", m_AutoPrcoName, strChan.GetBuffer(0));
		StoreQueryResult pResult = query.store(cSql, strlen(cSql));
		if (!pResult)
		{
			CallBack_LogReport(Input->nChan, 3, "AutoDialout_MultiCom error1\n");
			time(&m_ChanInfo[Input->nChan].LastNoDialoutTime);
			pthread_mutex_unlock(&m_DialoutMutex);
			return -1;
		}
        
        
        for (int i = 1; query.more_results(); ++i)
		{
			query.store_next(); //必须取完结果
		}

		sprintf(cSql, "select @phoneno,@uuid,@projectid,@batchid,@companyid,@displaynum,@dialtype");
		pResult = query.store(cSql, strlen(cSql));
		if (!pResult)
		{
			CallBack_LogReport(Input->nChan, 3, "AutoDialout_MultiCom error2\n");
			time(&m_ChanInfo[Input->nChan].LastNoDialoutTime);
			pthread_mutex_unlock(&m_DialoutMutex);
			return -1;
		}

         好了,问题解决!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值