PostgreSQL异步操作

转载 胡辉 在PG交流群分享:

异步操作
有几种情况下后端会发送一些并非由特定前端命令流传达的消息。在任何时候前端都必须准 备处理这些消息,即使它是并未参与一个查询。在最低限度下,我们应该在开始读取查询响 应之前检查这些情况。
NoticeResponse消息有可能是因为外部的活动而产生的;比如,如果数据库管理员进行一 次“快速”数据库关闭,那么后端将在关闭连接之前发送一个NoticeResponse来表明这些。 相应地,前端应该总是准备接受和显示NoticeResponse消息,即使连接事实上是空闲的。
如果任何时候有任何参数值的活跃值改变且后端认为前端应该知道这些,那么都会产生 ParameterStatus消息。这种情况最常见发生的情形是对前端执行的一个SET命令进行响应, 并且这种情况实际上是同步的 — 但是也有可能是数据库管理员改变了配置文件然后项服务 器发出SIGHUP信号导致了参数状态的变化。同样,如果一个SET命令回滚,那么也会生成一 个合适的ParameterStatus 消息以报告当前有效值。

 

目前,系统内有一套会生成ParameterStatus消息的写成硬代码的参数,它们是: (serv- er_encoding,TimeZone 和 integer_datetimes 在 8.0 版本之前没有报告。stan- dard_conforming_strings 在版本 8.1 之前没有报告。) 请注意 serv- er_version, server_encoding 和 integer_datetimes 是伪参数,启动后不能 修改。 这些可能在将来改变,或者甚至是变成可以配置的。 因此,前端应该简单地忽 略那些它不懂或者不关心的 ParameterStatus。 server_version、 server_encod- ing、 client_encoding、 application_name、 is_superuser、 session_autho- rization、 DateStyle、 IntervalStyle、 TimeZone、 integer_datetimes以 及 standard_conforming_strings (server_encoding、TimeZone以及integer_date- times在版本8.0之前不会被报告; standard_conforming_strings在版本8.1之前不会被报 告; IntervalStyle在版本8.4之前不会被报告; application_name在版本9.0之前不会被报 告)。 注意server_version、server_encoding以及integer_datetimes是伪参数,它们不 能在启动之后被改变。这种设置可能在未来改变,甚至变成可配置的。相应地,一个前端应 该简单地忽略那些与它不懂或者不关心的参数相关的ParameterStatus。
如果前端发出一个LISTEN命令, 那么无论何时在为同一个通道名NOTIFY时,后端将发送一 个NotificationResponse消息(不要和NoticeResponse搞混!)。
Note
目前,NotificationResponse只能在一个事务外面发送,因此它将不会在一个 命令响应序列中间出现,但是它可能正好在ReadyForQuery之前出现。不过, 在前端逻辑中做上述假设是不明智的。好的做法是在协议的任何点上都可以接 受NotificationResponse。

 

取消正在处理的请求
在一条查询正在处理的时候,前端可以请求取消该查询。这种取消请求不是直接通过打开的 连接发送给后端的,这么做是因为实现的效率:我们不希望后端在处理查询的过程中不停地 检查前端来的输入。 取消请求应该相对而言比较少见,所以我们把取消做得稍微笨拙一 些,以便不影响正常状况的性能。
要发出一条取消请求,前端打开一个与服务器的新连接并且发送一条CancelRequest消息, 而不是通常在新连接中经常发送的StartupMessage消息。服务器将处理这个请求然后关闭连 接。 出于安全原因,对取消请求消息不做直接的响应。
除非CancelRequest消息包含在连接启动过程中传递给前端的相同的关键数据(PID和密 钥),否则它将被忽略。如果该请求匹配当前运行着的后端的PID和密钥, 则退出当前查询 的处理(目前的实现里采用的方法是向正在处理该查询的后端进程发送一个特殊的信号)。
取消信号可能产生或者不产生效果 — 例如,如果它在后端完成查询的处理后到达,那么它 就没有做用。如果取消起作用了,会导致当前命令伴随着一个错误消息提前退出。
这么做是对安全性和有效性通盘考虑的结果,前端没有直接的方法获知一个取消请求是否成 功。它必须继续等待后端对查询响应。发出一个取消仅仅是增加了当前查询快些结束的可能 性, 同时也增加了当前查询会伴随着一条错误消息失败而不是成功执行的可能性。
因为取消请求是通过新的联接发送给服务器而不是通过平常的前端/后端通讯链接,所以取 消请求可能被任意进程发出的,而不仅仅是要取消查询的前端。 这样可能对创建多进程应 用提供了更多的灵活性。同时这样也带来了安全风险,因为任何一个非授权用户都可能试图 取消查询。这个安全风险通过要求在取消请求中提供一个动态生成的密钥来解决。

 

终止
通常优雅的终止过程是前端发送一条Terminate消息并且立刻关闭连接。一旦收到消息,后 端马上关闭连接并且终止。
在少数情况下(比如一个管理员命令数据库关闭),后端可能在没有任何前端请求的情况下 断开连接。在这种情况下,后端将在它断开连接之前尝试发送一个错误或者通知消息给出断 开的原因。
其它终止的情况发生在各种失败的场合,比如某一方的内核转储、失去通讯链路、丢失了消 息边界同步等。不管是前端还是后端看到了一个意外的连接关闭,那么它应该清理现场并且 终止。 如果前端不想终止自己,那么它有一个选项是重连服务器的方法启动一个新的后 端。如果收到了一个无法识别的消息类型,那么我们也建议关闭连接,因为出现这种情况可 能意味着是丢失了消息边界的同步。
不管是正常还是不正常的终止,任何打开的事务都会回滚而不是提交。不过,我们应该注意 的是如果一个前端在一个非SELECT查询正在处理的时候断开, 那么后端很可能在发现断开 之前先完成查询的处理。如果查询处于任何事务块之外(BEGIN ... COMMIT序列),那么其 结果很可能在得知断开之前被提交。

 

SSL会话加密
如果编译PostgreSQL的时候打开了SSL支持,那么前后端通讯就可以用SSL加密。 这样就提 供了一种在攻击者可能捕获会话通讯数据包的环境下保证通讯安全的方法。 
要开始一次SSL加密连接,前端先是发送一个SSLRequest消息,而不是StartupMessage。然 后服务器以一个包含S或N的字节响应,分别表示它愿意还是不愿意进行SSL。如果此时前端 对响应不满意, 那么它可以关闭连接。要在S之后继续,那么先进行与服务器的SSL启动 握手(没有在这里描述,是SSL规范的一部分)。 如果这些成功了,那么继续发送普通的 StartupMessage。这种情况下,StartupMessage和所有随后的数据都将由SSL加密。要在N之 后继续,则发送普通的StartupMessage并不适用加密继续处理。
前端应该也准备处理一个来自服务器的给SSLRequest的ErrorMessage响应。这种情况只在服 务器早于PostgreSQL的SSL支持的情况下才会出现(这种服务器现在非常古老,并且可能不 再存在了)。在这种情况下,连接必需关闭,但是前端可以选择打开一个新的连接然后不使 用SSL进行连接。
一个初始化的 SSLRequest 也可以用于打开来用于发送一条 CancelRequest 消息的联接中。
如果协议本身并未提供某种方法强制SSL加密,那么管理员可以把服务器配置为拒绝未加密 的会话,这是认证检查的一个副产品。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值