【问题标题】:Why does `libpq` use polling rather than notification for data fetch?为什么`libpq` 使用轮询而不是通知来获取数据?
【发布时间】:2013-10-12 14:42:31
【问题描述】:

我正在阅读libpq 参考资料。它同时具有同步和异步方法。但是我发现了一些奇怪的东西。

当我看到PQsendQuery 函数时,它似乎发送了一个查询并立即返回。我希望回调函数会得到通知,但没有这样的事情,手册说 poll 以获取数据可用性。

我不明白为什么异步方法是用轮询的方式写的。无论如何,由于libp 是官方的客户端实现,我相信这种设计应该有充分的理由。那是什么?还是我错过了其他地方提到的正确回调内容?

【问题讨论】:

  • 请注意:libpqPQsocket 函数,它返回套接字的 文件描述符。要获得数据可用性通知,请使用系统 API 监视此套接字。 (kqueuelibdispatch 等)
  • 现在我终于明白了这个设计。这只是阻塞与非阻塞 style 的区别,API 的形式对性能真的没有影响。

标签: postgresql libpq


【解决方案1】:

在单线程程序的执行模型中,执行流程不会被从异步查询(或更一般的网络套接字)返回的数据中断。只有信号(SIGTERM 和朋友)可能会中断流程,但信号不能与传入的数据挂钩。

这就是为什么无法通过回调来获得传入数据的通知的原因。如果您的代码不调用它,那么发出回调所必需的 libpq 中的一段代码将永远不会运行。如果你必须调用它,那就违背了回调的全部意义。

有像 Qt 这样的库提供回调,但它们是从头开始构建的,具有充当事件处理器的主循环。用户代码以回调的形式组织,并且可以对传入数据进行基于事件的处理。但在这种情况下,库拥有执行流的所有权,这意味着它的主循环会轮询数据源。这只是将责任转移到 libpq 之外的另一段代码。

【讨论】:

  • 看来libpq 是为单线程程序设计的。性能好吗?
  • @Eonil:任何网络客户端都必须等待套接字。 libpq 只是将其公开给库用户,从而可以将 libpq 与现有事件库一起使用,例如 libevent 或 Linux epoll。这使得libpq 比使用阻塞客户端(例如kegel.com/c10k.html#threaded)更具可扩展性,而不是浪费线程在数据库上等待和等待。所以是的,它对性能非常有好处。
【解决方案2】:

此页面描述了我如何获得异步结果获取的通知。

http://www.postgresql.org/docs/9.3/static/libpq-events.html#LIBPQ-EVENTS-PROC

PGEVT_RESULTCREATE

结果创建事件被触发以响应任何查询执行 生成结果的函数,包括 PQgetResult。这个事件 只有在成功创建结果后才会触发。

typedef 结构 { PGconn *conn; PGresult *结果; } PGEventResult创建;当收到 PGEVT_RESULTCREATE 事件时,应该将 evtInfo 指针转换为 PGEventResult 创建 *. conn 是用于生成 结果。这是初始化任何 instanceData 的理想位置 需要与结果相关联。如果事件过程失败, 结果将被清除并传播失败。这 事件过程不能尝试为自己 PQclear 结果对象。 返回失败代码时,所有清理必须执行为 no 将发送 PGEVT_RESULTDESTROY 事件。

【讨论】:

  • 这不会改变在PQsendQuery 之后进行轮询的需要。如果你不这样做,这个事件将永远不会被触发。
猜你喜欢
  • 2012-09-13
  • 2016-01-16
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
  • 2022-01-12
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
相关资源
最近更新 更多