PostgreSQL技术内幕13:PostgreSQL通讯协议

news2024/11/28 16:29:11

文章目录

    • 0.简介
    • 1.PG通讯协议
      • 1.1 消息格式
      • 1.2 消息交互流程
        • 1.2.1 启动流程
        • 1.2.2 简单查询流程
        • 1.2.3 扩展查询
          • 1.2.3.1 pipelining
        • 1.2.4 取消流程
        • 1.2.5 结束流程
        • 1.2.6 copy流程
        • 1.2.7 错误和通知

0.简介

之前文章对于PG的内部模块做了一些介绍,接下来对PG和外部交互的部分进行介绍,本文主要介绍通讯协议的概念和PG中的消息格式和交互流程。

1.PG通讯协议

通讯协议,就是通信双方对数据传输和解析的一种约定。遵守协议的双方可以进行正常的“交流”。对于PG,其外部的客户端(像psql,JDBC,PgAdmin等)都需要遵循PG的通信协议才能正确的进行通信,下面主要针对PG 7.4 版本开始使用的 Protocol v3.0 版本介绍,该协议支持 TCP/IP 和 Unix 域套接字。下面从数据格式,消息类型和传输流程来分别进行介绍。

1.1 消息格式

消息的格式是:第一个字节标识消息的类型,随后用四个字节标识消息的长度,然后是消息体。

在这里插入图片描述
其解析过程可以参考SocketBackend函数


static int
SocketBackend(StringInfo inBuf)
{
  int      qtype;

  /*
   * Get message type code from the frontend.
   */
  HOLD_CANCEL_INTERRUPTS();
  pq_startmsgread();
  qtype = pq_getbyte();

  if (qtype == EOF)      /* frontend disconnected */
  {
    //
  }

  /*
   * Validate message type code before trying to read body; if we have lost
   * sync, better to say "command unknown" than to run out of memory because
   * we used garbage as a length word.
   *
   * This also gives us a place to set the doing_extended_query_message flag
   * as soon as possible.
   */
  switch (qtype)
  {
    case 'Q':        /* simple query */
      doing_extended_query_message = false;
      if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
      {
        /* old style without length word; convert */
        if (pq_getstring(inBuf))
        {
          if (IsTransactionState())
            ereport(COMMERROR,
                (errcode(ERRCODE_CONNECTION_FAILURE),
                 errmsg("unexpected EOF on client connection with an open transaction")));
          else
          {
            /*
             * Can't send DEBUG log messages to client at this
             * point. Since we're disconnecting right away, we
             * don't need to restore whereToSendOutput.
             */
            whereToSendOutput = DestNone;
            ereport(DEBUG1,
                (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST),
                 errmsg("unexpected EOF on client connection")));
          }
          return EOF;
        }
      }
      break;

    case 'F':        /* fastpath function call */
      doing_extended_query_message = false;
      if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
      {
        if (GetOldFunctionMessage(inBuf))
        {
          if (IsTransactionState())
            ereport(COMMERROR,
                (errcode(ERRCODE_CONNECTION_FAILURE),
                 errmsg("unexpected EOF on client connection with an open transaction")));
          else
          {
            /*
             * Can't send DEBUG log messages to client at this
             * point. Since we're disconnecting right away, we
             * don't need to restore whereToSendOutput.
             */
            whereToSendOutput = DestNone;
            ereport(DEBUG1,
                (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST),
                 errmsg("unexpected EOF on client connection")));
          }
          return EOF;
        }
      }
      break;

    case 'X':        /* terminate */
      doing_extended_query_message = false;
      ignore_till_sync = false;
      break;

    case 'B':        /* bind */
    case 'C':        /* close */
    case 'D':        /* describe */
    case 'E':        /* execute */
    case 'H':        /* flush */
    case 'P':        /* parse */
      doing_extended_query_message = true;
      /* these are only legal in protocol 3 */
      if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
        ereport(FATAL,
            (errcode(ERRCODE_PROTOCOL_VIOLATION),
             errmsg("invalid frontend message type %d", qtype)));
      break;

    case 'S':        /* sync */
      /* stop any active skip-till-Sync */
      ignore_till_sync = false;
      /* mark not-extended, so that a new error doesn't begin skip */
      doing_extended_query_message = false;
      /* only legal in protocol 3 */
      if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
        ereport(FATAL,
            (errcode(ERRCODE_PROTOCOL_VIOLATION),
             errmsg("invalid frontend message type %d", qtype)));
      break;

    case 'd':        /* copy data */
    case 'c':        /* copy done */
    case 'f':        /* copy fail */
      doing_extended_query_message = false;
      /* these are only legal in protocol 3 */
      if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
        ereport(FATAL,
            (errcode(ERRCODE_PROTOCOL_VIOLATION),
             errmsg("invalid frontend message type %d", qtype)));
      break;

    default:

      /*
       * Otherwise we got garbage from the frontend.  We treat this as
       * fatal because we have probably lost message boundary sync, and
       * there's no good way to recover.
       */
      ereport(FATAL,
          (errcode(ERRCODE_PROTOCOL_VIOLATION),
           errmsg("invalid frontend message type %d", qtype)));
      break;
  }

  /*
   * In protocol version 3, all frontend messages have a length word next
   * after the type code; we can read the message contents independently of
   * the type.
   */
  if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
  {
    if (pq_getmessage(inBuf, 0))
      return EOF;      /* suitable message already logged */
  }
  else
    pq_endmsgread();
  RESUME_CANCEL_INTERRUPTS();

  return qtype;
}

1.2 消息交互流程

1.2.1 启动流程

在这里插入图片描述

客户端首先发送startup packet到服务器,服务器判断是否需要授权信息,需要的话这发送权限认证请求要求客户端发送密码,权限验证后进行一些参数信息传递,最后发送readyforquery表明连接创建成功。

1.2.2 简单查询流程

在这里插入图片描述

客户端会发送一个Query消息,服务端处理请求,然后返回查询结果,查询结果包含两部分,一是结构,即RowDescription(如列名,类型,长度);另外一个是数据,即DataRow(一行数据).
每个sql结束后都会返回一个commandcomplete,查询请求结束后回回复一条ReadyForQuery。

1.2.3 扩展查询

在这里插入图片描述

扩展查询将一个查询分为多个步骤,客户端先给服务的发送Parse消息,该消息包含参数化sql,服务端收到消息后,调用exec_parse_message 函数进行处理,进行语法分析、语义分析和重写,同时会创建一个 Plan Cache 的结构,用于缓存后续的执行计划;然后客户端发送bind消息,携带具体参数值,服务端收到该消息后,调用 exec_bind_message 函数进行处理;然后客户端发送describe,获取结果的列名,类型等信息;然后客户端发送execute去获取DataRow;最后Sync是扩展协议的请求消息结束标识。

1.2.3.1 pipelining

扩展查询允许使用流水线,即发送的一系列查询无需等待较早查询完成,减少给定系列操作的网络所需往返次数。但是需要考虑一个步骤失败,后续步骤已经发送给服务器的问题。

1.2.4 取消流程

在查询期间,客户端可能会请求取消查询,为了不让服务端在处理时不断检查来自客户端的新输入,取消请求采用的方式是打开一个新连接然后发送CancelRequet请求,而不是StartUp。那么如何知道要取消哪一个请求?依靠的是查询startup阶段,服务端返回给客户端的进程id和一个取消码。

1.2.5 结束流程
正常终止通过客户端发送的terminate终止消息来关闭连接,在异常常见下(数据库关闭),服务段可能没有收到请求就断开连接,在这种常见下,服务端会尝试在关闭连接之前发送错误或通知消息,给出原因。
1.2.6 copy流程

Copy 子协议对应三种模式:

copy-in 导入数据,对应命令 COPY FROM STDIN

copy-out 导出数据,对应命令 COPY TO STDOUT

copy-both 用于 walsender,在主备间批量传输数据

以 copy-in 为例,服务端收到 COPY 命令后,进入 COPY 模式,并回复 CopyInResponse。随后客户端通过 CopyData 消息传输数据,CopyComplete 消息标识数据传输完成,服务端收到该消息后,发送 CommandComplete 和 ReadyForQuery 消息,消息流如下:

在这里插入图片描述

1.2.7 错误和通知

错误和通知通过ErrorResponse 和通知消息 NoticeResponse来返回,具体含义如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189436.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GS-SLAM论文阅读笔记-MGSO

前言 MGSO首字母缩略词是直接稀疏里程计(DSO)&#xff0c;我们建立的光度SLAM系统和高斯飞溅(GS)的混合。这应该是第一个前端用DSO的高斯SLAM&#xff0c;不知道这个系统的组合能不能打得过ORB-SLAM3&#xff0c;以及对DSO会做出怎么样的改进以适应高斯地图&#xff0c;接下来…

【有啥问啥】SE(Squeeze-and-Excitation)架构详解

SE&#xff08;Squeeze-and-Excitation&#xff09;架构详解 在深度学习&#xff0c;特别是计算机视觉领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;的发展日新月异。为了进一步提升CNN的特征提取能力和模型性能&#xff0c;研究者们不断探索新的网络架构和组件。…

向量数据库|第1期|从零开始学习

向量数据库|第1期|从零开始学习 1、向量数据库中的基本概念 1.1 什么是余弦 余弦函数是一种三角函数&#xff0c;在直角三角形中&#xff0c;某个锐角的余弦为&#xff1a;临边与斜边的比值&#xff0c;如下图cosAb/c。引申到任意三角形中&#xff0c;即余弦定理&#xff1a;…

2024年7月大众点评全国酒吧前百名城市分析

在做一些城市分析、学术研究分析、商业选址、商业布局分析等数据分析挖掘时&#xff0c;大众点评的数据参考价值非常大&#xff0c;截至2024年7月&#xff0c;大众点评美食店铺剔除了暂停营业、停止营业后的最新数据情况分析如下。 分析研究的字段维度包括大众点评数字id、字母…

LSM6DSV16X基于MLC智能笔动作识别(3)----MEMS Studio训练数据

LSM6DSV16X基于MLC智能笔动作识别.3--MEMS Studio训练数据 概述视频教学样品申请源码下载硬件准备选择MEMS导入数据配置窗口长度和量程配置滤波器选择特征数据设备树生成决策树生成参考程序转换UCF文件 概述 MEMS-Studio是一套完整的桌面软件解决方案&#xff0c;专为开发嵌入…

认知杂谈98《抵御噪声干扰》

内容摘要&#xff1a; “能量掠夺”是指他人负面言行对我们情绪和心理状态的不良影响&#xff0c;使我们感到沮丧或愤怒。这种影响可能源于我们内心对自身价值认同的不坚定&#xff0c;以及过分在意他人的看法。 要避免能量掠夺&#xff0c;我们需要建立心理防线&#xff0c;学…

Xilinx Vitis IDE启动时失去响应的解决办法

在启动Xilinx Vitis IDE时&#xff0c;有时候会遇到卡死的情况&#xff0c;无论是直接启动还是从Vivado的菜单中启动都一样。参考Xilinx官网的解决办法&#xff1a;&#xff08;一直到2023.1版本都是可以解决的&#xff0c;之后的版本没测过。&#xff09; Widget (amd.com) …

Leetcode—279. 完全平方数【中等】

2024每日刷题&#xff08;169&#xff09; Leetcode—279. 完全平方数 实现代码 class Solution { public:int numSquares(int n) {vector<int> dp(n 1, n);dp[0] 0;dp[1] 1;for(int i 2; i < n; i) {for(int j 1; j * j < i; j) {dp[i] min(dp[i], dp[i -…

Oracle中ADD_MONTHS()函数详解

文章目录 前言一、ADD_MONTHS()的语法二、主要用途三、测试用例总结 前言 在Oracle数据库中&#xff0c;ADD_MONTHS()函数用于在日期中添加指定的月数。 一、ADD_MONTHS()的语法 ADD_MONTHS(date, n) 其中&#xff0c;date是一个日期值&#xff0c;n是一个整数值&#xff0c…

C语言高阶【2】--动态内存管理【2】--柔性数组(这是个全新的知识点,不想了解一下吗?)

本章概述 柔性数组总结C/C中程序内存划分彩蛋时刻&#xff01;&#xff01;&#xff01;&#xff01; 柔性数组 数组这个东西&#xff0c;我想大家应该都不陌生了吧。但是&#xff0c;柔性数组这个东西可能你是第一次听说。 柔性数组概念&#xff1a;在C99之前是没这个东西的…

基于Flux的文生高清图片

Flux模型生成的图片画质极佳&#xff0c;改进修复了手的问题&#xff0c;支持字体生成和排版&#xff0c;训练参数大&#xff0c;风格多样&#xff0c;分辨率弹性好&#xff0c;embedding通用性好&#xff0c;不需要输入负面提示词。 安装ComfyUI ComfyUI下载安装 下载和配置…

计算机网络:计算机网络概述 —— 网络拓扑结构

文章目录 网络拓扑总线型拓扑特点缺陷 星型拓扑特点缺陷 环型拓扑特点缺陷 网状型拓扑优点缺陷 树型拓扑特点缺陷 网络拓扑 网络拓扑指的是计算机网络中节点&#xff08;计算机、交换机、路由器等&#xff09;之间物理或逻辑连接的结构。网络拓扑定义了节点之间的布局、连接方…

方法重载(Overload)

前言 在前面的学习中&#xff0c;我们学到了重写(Override),这里我们主要进行重载(Overload)的介绍&#xff0c;同时对重写和重载的区别进行分析。 1. 重载(Overload) #方法重载 在同一个类中定义多个同名但参数不同的方法。我们称方法与方法之间构成方法重载 在Java中&…

【宽搜】1. 层序遍历模板讲解

题目描述 题目链接&#xff1a;N叉树的层序遍历 层序遍历流程 请仔细阅读下图&#xff1a; 根据上图的流程&#xff0c;下面再明确几个问题&#xff1a; 1. 为什么要使用队列&#xff1f; 队列是先进先出的数据结构&#xff0c;在数的层序遍历中&#xff0c;需要先将节点p…

Pikachu-Sql Inject-宽字节注入

基本概念 宽字节是相对于ascII这样单字节而言的&#xff1b;像 GB2312、GBK、GB18030、BIG5、Shift_JIS 等这些都是常说的宽字节&#xff0c;实际上只有两字节 GBK 是一种多字符的编码&#xff0c;通常来说&#xff0c;一个 gbk 编码汉字&#xff0c;占用2个字节。一个…

【C++打怪之路Lv6】-- 内存管理

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

软考鸭微信小程序:助力软考备考的便捷工具

一、软考鸭微信小程序的功能 “软考鸭”微信小程序是一款针对软考考生的备考辅助工具&#xff0c;提供了丰富的备考资源和功能&#xff0c;帮助考生提高备考效率&#xff0c;顺利通过考试。其主要功能包括&#xff1a; 历年试题库&#xff1a;小程序内集成了历年软考试题&…

PyTorch实现卷积神经网络CNN

一、卷积神经网络CNN 二、代码实现&#xff08;PyTorch&#xff09; 1. 导入依赖库 import torch from torch import nn, optim from torchvision import datasets, transforms from torch.utils.data import DataLoader nn&#xff1a;包含了torch已经准备好的层&#xff0c…

Pikachu-Unsafe Fileupload-服务端check

MIME MIME是Multipurpose Internet Mail Extensions &#xff08;多用途互联网邮件扩展类型&#xff09;的缩写&#xff0c;用来表示文件、文档、或字节流的性质和格式。是设定某种扩展名的文件用一种应用程序来打开的方式类型&#xff0c;当该扩展名文件被访问的时候&#xff…

论文阅读笔记-A Comparative Study on Transformer vs RNN in Speech Applications

前言 介绍 序列到序列模型已广泛用于端到端语音处理中,例如自动语音识别(ASR),语音翻译(ST)和文本到语音(TTS)。本文着重介绍把Transformer应用在语音领域上并与RNN进行对比。与传统的基于RNN的模型相比,将Transformer应用于语音的主要困难之一是,它需要更复杂的配…