本文PG代码版本为:REL\_14\_STABLE(PG 14稳定分支)。 ## psql连接创建服务进程 客户端psql连接PG server成功后,PostMaster(守护进程)会fork出来一个服务进程(Backend),如下所示: ``` [yz@localhost ~]$ ps -ef | grep postgres yz 14560 1 0 11:25 ? 00:00:00 /home/yz/postgresql/pg_bin/bin/postgres -D /home/yz/postgresql/pg_data yz 14627 14560 0 11:25 ? 00:00:00 postgres: checkpointer yz 14628 14560 0 11:25 ? 00:00:00 postgres: background writer yz 14629 14560 0 11:25 ? 00:00:00 postgres: walwriter yz 14630 14560 0 11:25 ? 00:00:00 postgres: autovacuum launcher yz 14631 14560 0 11:25 ? 00:00:00 postgres: stats collector yz 14632 14560 0 11:25 ? 00:00:00 postgres: logical replication launcher yz 14637 14431 0 11:25 pts/0 00:00:00 psql -p 7404 postgres yz 14638 14560 0 11:25 ? 00:00:00 postgres: yz postgres [local] idle ``` 14638是为14637服务的进程,其父进程为14560。 ## 监听端口 之后,服务进程进入无限循环,监听连接端口上的消息,即: ```c void PostgresMain(int argc, char *argv[], const char *dbname, const char *username) { /* * Non-error queries loop here. */ for (;;) { // read a command firstchar = ReadCommand(&input_message); switch (firstchar) { case 'Q': /* simple query */ { exec_simple_query(query_string); } } } ``` ## psql发送查询 假设psql执行一条select命令,则psql通过libpq将消息发送给后端服务进程: ``` (gdb) bt #0 0x00007f4ef75b2400 in PQsendQuery () from /home/yz/postgresql/pg_bin/lib/libpq.so.5 #1 0x00007f4ef75b3260 in PQexec () from /home/yz/postgresql/pg_bin/lib/libpq.so.5 #2 0x000000000040d2af in SendQuery () #3 0x000000000041ebb4 in MainLoop () #4 0x0000000000406347 in main () ``` PQsendQuery实际调用PQsendQueryInternal,可以看到以下代码: ```c if (pqPutMsgStart('Q', conn) < 0 || pqPuts(query, conn) < 0 || pqPutMsgEnd(conn) < 0) { /* error message should be set up already */ pqRecycleCmdQueueEntry(conn, entry); return 0; } ``` 'Q'指令就是在这里生成的。 ## 执行 服务进程收到查询请求,执行主要由: ``` exec_simple_query ``` 负责执行,包括语法解析、生成执行计划、优化、算子执行等。 执行过程中,如果有并行,则需要发信号(signal)给PostMaster,PostMaster会fork worker进程。