【问题标题】:How to prematurely finish mysql_use_result() / mysql_fetch_row()?如何过早完成 mysql_use_result() / mysql_fetch_row()?
【发布时间】:2018-04-27 12:09:14
【问题描述】:

我正在为 MySQL 5.5 编写我的第一个 C 客户端,并且在文档中偶然发现了 the following page。几乎在最后,它说(粗体强调我的,斜体强调不是我的):

mysql_use_result() 的一个优点是 [...]。缺点是 [...]。 此外,您必须检索所有行,即使您 在检索过程中确定您已经找到了您的信息 正在寻找。

最后一句话我不清楚。

1) 如果我不遵循这条线会发生什么?

2) 我认为,如果我确定我有足够的信息,那么实际上一定有一种方法可以提前结束获取行(否则,整个事情在我眼中没有多大意义)。

我知道如果我只是停止获取行然后尝试执行下一条语句,可能会发生一些不好的事情,但是没有类似 mysql_finish_fetch() 或类似的函数吗?

如果我打电话给mysql_free_result() 会发生什么?即使我还没有获取所有行,这也应该释放结果,因此在检索过程中调用它并继续我想做的任何事情都应该是安全的。我错了吗?

【问题讨论】:

  • 有据可查:When using mysql_use_result(), you must execute mysql_fetch_row() until a NULL value is returned, otherwise, the unfetched rows are returned as part of the result set for your next query. The C API gives the error Commands out of sync; you can't run this command now if you forget to do this!
  • 您通常应该准确地查询您需要的信息。查询更多然后开始在结果中寻找“重要部分”是错误的方法!如果您确实需要以如此复杂的方式进行过滤,而使用普通 sql 无法实现,请使用存储过程
  • @Ctx 我同意你的第二条评论。尽管如此,一些具有 MySQL 绑定的脚本语言(例如 Perl)具有“语句/获取完成功能”,我想知道它是如何工作的。我在某些非常方便的情况下使用了它。
  • 我认为这些也必须在后台获取剩余的行

标签: mysql c libmysql


【解决方案1】:

这听起来像是 MySQL 向客户端公开的内部线程问题。将其归结为各种MySQL gotchas。简而言之,MySQL 内部显然有有限数量的“搜索器”,而使用 mysql_use_result() 显然会将其中一个专用于您的 API 请求。此外,MySQL 显然没有公开的 API 调用来取消这样的请求。唯一的选择是看到提取直到结束。

稍长的版本:在内部,MySQL 的游标显然有一个单一的代码路径——我想是为了在常见情况下的性能。当光标找不到更多结果时,该代码路径退出。当您使用更常见的mysql_store_result() 时,MySQL 在将结果返回给应用程序之前已经这样做了。但是,当您使用mysql_use_result() 时,MySQL 要求您执行迭代其余结果集以清除游标的“脏活”。有趣。

来自documentation

mysql_use_result() 启动结果集检索,但并不像mysql_store_result() 那样实际将结果集读入客户端。相反,必须通过调用mysql_fetch_row() 单独检索每一行。这直接从服务器读取查询结果,而不将其存储在临时表或本地缓冲区中,这比mysql_store_result() 更快并且使用更少的内存。客户端只为当前行和一个可能增长到max_allowed_packet字节的通信缓冲区分配内存。

另一方面,如果您在客户端对每一行进行大量处理,或者如果将输出发送到用户可以键入的屏幕,则不应使用 mysql_use_result() 锁定读取^S(停止滚动)。这会占用服务器并阻止其他线程更新从中获取数据的任何表。

使用mysql_use_result() 时,您必须执行mysql_fetch_row() 直到返回NULL 值,否则,未提取的行将作为下一个查询的结果集的一部分返回。如果您忘记这样做,C API 会给出错误Commands out of sync; you can't run this command now

所以,要真正回答你的问题:

1) 如果我不遵循这条线会发生什么?

C API 会返回错误信息:Commands out of sync; you can't run this command now

2) 我认为,如果我确定我有足够的信息,那么实际上一定有一种方法可以提前结束获取行(否则,整个事情在我眼中没有多大意义)。

有人会想,但不会。您必须完全迭代结果集。

【讨论】:

  • 当然 MySQL 会清理,如果仍有大量数据未决,重新连接确实是一种解决方法......但实际上应该只询问实际需要的数据,否则查询或数据库设计坏了,
  • @Ctx 鉴于上述不明显的实现,我的幽默尝试很糟糕。但也许你是对的。最后让我编辑一下。
  • 它开始变得有意义了。那么mysql_free_result()只是释放客户端资源,却不与服务器通信告诉服务器“中止查询”?
  • @Binarus “没有说‘中止查询’:正确。有人可能会说“我们在C 土地上,那里什么都没有。我们必须做所有事情。包括清理。”
  • 这是否适用于每个连接?如果另一个连接犯了这个错误,我的连接会受到影响吗?
猜你喜欢
  • 2011-02-24
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多