【PostgreSQL】客户端请求处理 PostgresMain()

PostgreSQL在接收到客户端连接后,通过主进程fork子进程来处理每个连接请求。在PostgresMain函数中,无限循环监听客户端的各类请求,如简单查询、参数化查询的parse、bind、execute等操作,还包括COPY子协议的处理。每个请求根据其类型进行不同的处理步骤,如解析、执行和绑定等。
根据启动流程,postgres 会调用 select 监听客户端连接,并 fork 子线程来单独负责这个连接的请求处理,代码:
postmaster.c PostmasterMain()     =>    主程序入口
postmaster.c ServerLoop()    =>    开始 main loop,for(;;)调用 linux's epoll_wait(2) 处理客户端链接。
postmaster.c ConnCreate()     =>    监听到客户端链接..
postmaster.c BackendStartup()     =>    fork子进程程处理当前链接
postmaster.c BackendRun()     =>  客户端子进程请求处理函数入口。  
postgres.c PostgresMain()     =>    开始客户端处理,for(;;)调用监听客户端请求
postgres.c ReadCommand()    =>    解析客户端指令,query、parse、bind、execute、close、describe、flush 等等。

客户端请求处理入口函数 PostgresMain(),会 for(;;)监听客户端请求:
void PostgresMain(const char *dbname, const char *username){
   int          firstchar;//解析出来的客户端请求
   // 设置信号处理
   if (am_walsender)
      WalSndSignals();
   else{ //..}
   // 预处理
   BaseInit();
   if (am_walsender)
      InitWalSender();
        // 开始监听客户端请求
   for (;;)
   {
      // 解析客户端请求
      firstchar = ReadCommand(&input_message);
               // 然后不同的请求进行不同的处理
      switch (firstchar)
      {
         case 'Q':        /* simple query */
         case 'P':        /* parse */
         case 'B':        /* bind */
         case 'E':        /* execute */
         case 'F':        /* fastpath function call */
         case 'C':        /* close */
         case 'D':        /* describe */
         case 'H':        /* flush */
         case 'S':        /* sync */
         case EOF:
         case 'X':
         case 'd':        /* copy data */
         case 'c':        /* copy done */
         case 'f':        /* copy fail */
         default:
      }
   }                    /* end of input-reading loop */
}

客户端消息类型如下:
case 'Q'
 /* simple query */    
exec_simple_query()
执行 insert、query、update 等。非参数化的请求。
case 'P'
 /* parse */
exec_parse_message()
参数化 Prepared-statement 的解析阶段:parse,对语法进行分析并重写,请求传递的是带参数占位符的sql语句。
case 'B'
/* bind */
exec_bind_message()
参数化 Prepared-statement 的解析阶段:bind,将上一阶段的 PreparedStatement 生成执行计划并绑定保存,后续相同的参数化请求可以复用,还需要对已有的计划进行校验。请求传递的是参数、参数格式和返回列格式。
case 'E'
/* execute */
exec_execute_message()
参数化 Prepared-statement 的解析阶段:execute,参数和计划 Portal 都有了直接执行请求。
case 'F'
/* fastpath function call */
case 'C'
 /* close */
case 'D':
/* describe */
exec_describe_statement_message()
exec_describe_portal_message()
客户端可以发送 Describe 消息获取 Statment(parse) 或 Portal(bind) 的元信息,即返回结果的列名,类型等信息,这些信息由 RowDescription 消息携带。如果请求获取 Statement 的元信息,还会返回具体的参数信息。
case 'H':   
 /* flush */
case 'S': 
/* sync */
使用参数化 Prepared-statement 的请求需要 sync 结尾。
case 'X':
case EOF:
case 'd':   
 /* copy data */
copy子协议
case 'c':    
/* copy done */
copy子协议
case 'f':   
/* copy fail */
copy子协议
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0x13

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值