分享
 
 
 

PostgreSQL数据库学习手册之libpq-C库---异步查询处理

王朝mssql·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

1.4. 异步查询处理

PQexec 函数对简单的同步应用里提交命令已经是足够用的了.但是它却有几个主要的缺陷:

*

PQexec 等待命令结束.应用可能有其他工作要做(例如维护用户界面),这时它可不希望阻塞在这里等待返回.

*

因为控制是藏在 PQexec内部,前端很难取消掉正进行着的命令.(可以通过信号控制器进行,但没有别的方法.)

*

PQexec 只能返回一个PGresult结构.如果提交的命令字符串包含多个 SQL 命令,除了最后一个PGresult以外都会被 PQexec 丢弃。

不想受到这些限制的应用可以改用下面的函数,这些函数也是构造 PQexec 的函数: PQsendQuery 和 PQgetResult。

使用这些(异步)功能以及 PQputline 和 PQputnbytes 的老一些的程序可能在等待数据发送给后端时阻塞住,为解决这样的问题,增加了函数 PQsetnonblocking.

旧应用可以忽略 PQsetnonblocking 的使用,维持原有的阻塞特征。新的程序可以利用 PQsetnonblocking 获得与后端完全非阻塞的联接。

*

PQsetnonblocking 把该联接的状态设置为非阻塞。

int PQsetnonblocking(PGconn *conn, int arg)

如果arg为 TRUE,把联接状态设置为非阻塞, 如果arg为 FALSE, 把联接状态设置为阻塞.如果 OK 返回 0,如果错误返回 -1. 此函数将确保对

在非阻塞状态,调用 PQputline,PQputnbytes, PQsendQuery 和 PQendcopy 的时候不被阻塞, 而是如果需要再次它们时将是返回一个错误(而不是阻塞)。

当把一个数据库的联接设置为非阻塞的模式并且调用了 PQexec,它将暂时把联接状态设置为阻塞模式直到 PQexec 完成。

在不久的将来将有更多的libpq会设计成在 PQsetnonblocking 方式下是安全的。

*

PQisnonblocking 返回数据库联接的阻塞状态。

int PQisnonblocking(const PGconn *conn)

如果联接设置为非阻塞状态,返回 1,如果是阻塞状态返回 0。

*

PQsendQuery 向服务器提交一个命令而不等待结果. 如果查询成功发送则返回 1,否则返回 0.此时,可以用PQerrorMessage 获取关于失败的信息).

int PQsendQuery(PGconn *conn,

const char *query);

在成功调用 PQsendQuery后,调用 PQgetResult 一次或者多次获取结果. 可以不再调用PQsendQuery (在同一次联接里) 直到 PQgetResult 返回 NULL,表明命令完成.

*

PQgetResult 等待从前面 PQsendQuery 调用返回的下一个结果, 然后返回之.当查询结束并且没有更多结果后返回 NULL.

PGresult *PQgetResult(PGconn *conn);

必须重复的调用 PQgetResult ,直到它返回 NULL, 表明该命令结束.(如果在没有活跃的命令时调用, PQgetResult 将只是立即返回 NULL.) 每个 PQgetResult 返回的非 NULL 结果都应该用前面 描述的 PGresult 访问函数进行分析. 不要忘了在结束分析后用 PQclear 释放每个结果对象. 注意, PQgetResult 只是在有查询激活而且必须的返回数据还没有被 PQconsumeInput 读取时阻塞.

使用 PQsendQuery 和 PQgetResult 解决了 PQexec的一个问题:如果一个命令字符串包含多个 SQL 命令,这些命令的结果可以独立的获得.(顺便说一句:这样就允许一种简单的重叠处理模式,前端可以处理一个查询的结果而后端可以仍然在处理同一命令字符串的后面的查询.)但是,调用 PQgetResult 将仍然导致前端被阻塞住直到后端完成下一个 SQL 命令.这一点可以通过合理的使用下面三个函数来避免:

*

PQconsumeInput 如果存在后端来的输入可用,则使用之.

int PQconsumeInput(PGconn *conn);

PQconsumeInput 通常返回 1 表明"没有错误",而返回 0 表明有某种错误发生, (同时设置 PQerrorMessage).注意这个结果并不表明实际上是否收集了数据.在调用 PQconsumeInput之后,应用可以检查 PQisBusy 和/或 PQnotifies 看一眼它们的状态是否改变.

PQconsumeInput 可以在应用还没有做好处理结果或通知的情况下被调用.这个过程将读取可用的数据并且在一个缓冲区里保存它,这样导致一个 select() 读准备好标识的生成.这样应用就可以使用 PQconsumeInput 立即清掉 select() 条件,然后在空闲的时候检查结果.

*

PQisBusy 在查询忙的时候返回 1 ,也就是说, PQgetResult 将阻塞住等待输入.一个 0 的返回表明这时调用 PQgetResult 可以确保不阻塞.

int PQisBusy(PGconn *conn);

PQisBusy 本身将不会试图从后端读取数据;所以必须先调用 PQconsumeInput ,否则忙状态将永远不会消除.

*

PQflush 试图把任何正在排队的数据冲刷到后端,如果成功(或者发送队列为空)返回 0,如果因某种原因失败返回EOF。

int PQflush(PGconn *conn);

在一个非阻塞的联接调用 select() 判断是否有响应到达之前需要调用一个 PQflush 。如果返回 0 则保证了与后端的发送队列里面没有待发送的数据。只有使用了 PQsetnonblocking 的应用需要这个。

*

PQsocket 获取用于后端联接套接字的文件描述符号. 一个有效的描述符应该是 >= 0;一个 -1 表明当前没有打开与后端的联接.

int PQsocket(const PGconn *conn);

PQsocket 应该用于获取准备调用 select() 的后端套接字描述符.这就允许一个应用使用阻塞的联接等待后端的响应或者其他条件.如果 select() 的结果表明可以从后端套接字读取数据,那么应该调用 PQconsumeInput 读取数据;之后,,PQisBusy,PQgetResult,和/或 PQnotifies 可用于处理返回信息.

非阻塞的联接(那些使用了 PQsetnonblocking的联接)在 PQflush 返回 0 之前,(这表明没有数据缓冲着等待发送给后端)不应该使用 select()。

一个使用这些函数的典型的前端将有一个主循环使用 select() 等待所有它必须处理的条件.其中一个条件将会是后端来的数据已准备好,从 select() 的角度来看就是 PQsocket 标识的文件描述符上已经有可读取的数据.当主循环侦测到输入准备好,它将调用PQconsumeInput 读取输入.然后可以调用 PQisBusy 返回 false (0)后面可以跟着 PQgetResult。同样它(用户应用)可以调用 PQnotifies测 NOTIFY 信息(参阅下面的 "异步通知").例子程序节里面给出了一个例子程序.

一个使用 PQsendQuery/PQgetResult 的前端同样也可以试图取消一个正在被后端处理的命令.

*

PQrequestCancel 要求 PostgreSQL 放弃处理当前命令.

int PQrequestCancel(PGconn *conn);

如果取消的请求成功发送,返回值是 1,否则是 0.(如果为假,PQerrorMessage 会告之为什么.)不过,取消请求的成功发送将不保证请求将产生作用.不管 PQrequestCancel 的返回值是什么,应用都必须继续使用 PQgetResult进行通常的后续的结果读取工作.如果取消动作生效,当前的命令将提前退出并返回一个错误结果.如果取消动作失败(也就是后端已经处理完命令了),那么将没有可见的结果.

注意:如果当前的命令是事务的一部分,取消动作将退出整个事务.

PQrequestCancel 可以很安全地从一个信号句柄里调用.所以,如果取消动作可以从信号句柄里发出的话,它也可以与简单的 PQexec一起使用.例如, psql 从一个SIGINT信号句柄里调用 PQrequestCancel ,因此允许交互地取消通过 PQexec 发出的查询.注意,如果没有与后端建立联接或者后端当前没有处理命令, PQrequestCancel 将不发生做用.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有