PostgresInternal

Postgres Internals 14 阅读笔记 Egor Rogov 的 PostgreSQL 14 Internals 读书笔记入口。中文在线版方便查阅,英文 PDF 方便离线精读。 资料 中文在线版:PostgreSQL 14 Internals(中文) 英文 PDF(本站电子书库):postgresql_internals-14_parts1-3_en.pdf PostgreSQL 14 Internals (EN, Parts 1–3) 新窗口打开 下载 数据组织 数据库 当初始化一个 PG 实例之后,PGDATA 会自动创建以下三种基础数据库: template0: 用来通过逻辑复制,或创建不同编码数据库的原型/样板; template1: 用户在此实例下创建所有其他数据库的模版,新建库都基于它; postgres: 自带的一个常规库;

September 11, 2026 · 1 min · 39 words · Me

PostgreSQL 1-1 源码安装 (linux / macos)

摘要 本文介绍介绍如何在2种个人PC中,使用源码安装PostgreSQL,包括: 在Windows操作系统中,如何基于VwWare虚拟机,搭建Linux环境。并在Linux中,通过postgreSQL源码进行编译安装。 在MacOS操作系统中,如何使用云服务器中的Linux操作系统,搭建postgreSQL源码编译与学习环境。 目录 1 在Windows中安装PostgreSQL 1.1 目的 1.2 准备 1.3 编译源码 1.4 配置快捷命令 2 在MacOS中安装PostgreSQL 2.1 问题 2.2 调研云服务商 2.3 选择云服务器 2.4 配置云服务器 2.5 下载postgreSQL源码 1 在Windows中安装PostgreSQL 1.1 目的 通过postgreSQL源码进行编译安装,主要目的是: 方便通过源码调试跟踪 直接修改以增加调试信息或新功能 1.2 准备 首先,介绍如何准备centOS虚拟机,并安装git、VSCode、gdb等工具 已有windows 10/11 x86物理机 window 10中,安装vmware vmware中,安装centOS虚拟机 http://mirrors.huaweicloud.com/centos/8.4.2105/isos/x86_64/ centOS中,安装git,以及中文输入法 centOS中,安装VSCode https://code.visualstudio.com/docs/setup/linux#_rhel-fedora-and-centos-based-distributions centOS中,安装PostgresSQL依赖的第三方开源软件 sudo yum install -y readline readline-devel openssl openssl-devel zlib zlib-devel # 但是,部分linux可能会裁剪应用,因此可能需要安装如下软件 sudo yum install -y bison bison-devel flex flex-devel #[参考](https://blog.csdn.net/Linjingke32/article/details/80393576) 安装调试工具 ...

January 21, 2025 · 3 min · 465 words · Me

PostgreSQL 1-2 进程架构

1 进程架构 1.1 进程架构 1.2 进程启动 1.3 进程通信 2 进程功能 2.1 postgres线程 1.2.1 postmaster进程 1.2.2 postgres进程 1.2.3 wal writer进程 1.2.4 background writer进程 1.2.5 checkpointer进程 1.2.6 autovacuum进程 1.2.7 statistics collector进程 1.2.8 archiver进程 1.2.9 logging collertor进程 1.3 进程通信 3 进程控制 1 进程架构 1.1 进程架构 postgresql 采用1+n+7的进程架构,包括: 1个postmaster进程 n个postgres进程 7个辅助进程:包括: bg writer进程: checkpointer进程: walwriter进程: autovacuum进程: archiver进程: statistics collector进程: log collectoer进程: 进程架构图如下图所示: 1.2 进程启动 先启动postmaster进程,再由poastermaster启动n+7进程。 在postmaster主函数中,进程启动顺序如下: main() # [主进程] 启动postmaster进程 PostmasterMain() pqsignal(SIGUSR1, sigusr1_handler); # 注册信号 SysLogger_Start() # [进程7] 启动log collector进程 StartupDataBase() -> StartupProcessMain() # 进行故障恢复 ServerLoop() BackendStartup() SysLogger_Start() # [进程n] 启动posters进程 StartCheckpointer() -> CheckpointerMain() # [进程2] 启动heckpointer进程 StartBackgroundWriter() -> BackgroundWriterMain() # [进程1] 启动bg writer进程 StartWalWriter() -> InitXLOGAccess() WalWriterMain() # [进程3] 启动walwriter进程 StartAutoVacLauncher() # [进程4] 启动autovacuum进程 pgstat_start() # [进程6] 启动 statistics collector进程 pgarch_start() # [进程5] 启动归档进程 maybe_start_bgworker() 1.3 进程通信 2 进程功能 本章介绍各进程的主要功能。 ...

January 21, 2025 · 5 min · 1025 words · Me

PostgreSQL 1-3 执行模块

1 整体流程 1.1 执行流程 应用->驱动:通过驱动的api建立连接,并执行SQL语句 驱动->服务端:通过libpq协议封装SQL语句,发送至服务端 服务端 postgres线程:接收SQL语句,调用exec_siple_query()开始处理SQL语句 SQL引擎 解析器:通过flex进行词法解析,通过yacc进行语法分析,生成解析树 分析器:对解析树进行语义分析:包括检查表是否存在等,生成查询树 重写器: 计划期:根据查询树生成执行计划 执行器:自顶向下执行各个算子,执行过程中会调用存储引擎统一接口 INSERT / UPDATE / DELETE ExecModifyTable 算子:EexecInsert / ExecUpdate / ExecDelete EexecInsert ExecMaterializeSlot ExecBRInsertTriggers /* ROW INSERT 触发器 */ ExecWithCheckOptions /* 检查约束 */ heap_insert /* 存储引擎统一接口 */ ExecInsertIndexTuples ExecARInsertTriggers /* AFTER ROW 触发器 */ ExecProcessReturning SELECT ExecIndexScan IndexNext() index_getnext() tid = index_getnext_tid(scan) index_fetch_heap(scan) heap_hot_search_buffer() PageGetItem()

January 21, 2025 · 1 min · 59 words · Me

PostgreSQL 1-4 存储模块

摘要 本博客以循序渐进的方式,依次简要介绍PostgreSQL存储模块的各个子模块的基础功能,提及内容适合数据库内核初学者。本博客旨在介绍核心原理,以便于理解为首,部分内容可能不会100%准确与具体,针对每个提及的子模块,之后会分别单独写博客详细介绍 目录 摘要 目录 1 概述 1.1 PostgreSQL的使用流程 1.2 PostgreSQL的基础架构 1.3 PostgreSQL的功能场景 1.4 PostgreSQL存储模块的介绍流程 2 执行模块 3 存储模块 3.1 存储结构 (1) data_directory (2) oid (3) data-file (4) page (5) tuple 3.2 关键机制 (1) mvcc (2) delete 3.3 执行流程 (1) input (2) heapam (3) trancation (4) fsm (5) buffer (6) smgr (7) vfd (8) vm (9) wal (10) wal-buffer 3.4 关键进程 (1) bgwriter (2) walwriter (3) checkpointer (5) walsender (6) autovacuum 3.5 关键流程 (1) heap_insert (2) heap_delete (3) heap_update (4) heap_scan 3.6 辅助机制 (1) index (2) recovery (3) backup (4) toast (5) logical 1 概述 1.1 PostgreSQL的使用流程 本博客仅讨论存储模块的关键原理。简而言之,PostgreSQL将数据合理地组织并存储在磁盘上,并向用户提供SQL接口,让其读写磁盘上的指定数据。以下是PostgreSQL简单工作流程: ...

January 21, 2025 · 4 min · 686 words · Me

PostgreSQL 1-5 initdb

initdb 流程 opengauss main # initdb.cpp canonicalize_path # PGDATA find_other_exec # 在gs_initdb bin目录下,查找gaussdb bin # 在$GAUSSHOME/share/postgrsql目录下,检查以下文件是否存在 check_input('postgres.bki, postgres.description, pg_hba.conf.sample, postgresql.conf.sample, ..., system_views.sql, ...') check_locale_encoding init_log gs_getenv_r('GAUSSLOG') write_version_file canonicalize_path('$PGDATA/PG_VERSION') fprintf(PG_MAJORVERSION = '9.2') setup_config readfile('$GAUSSHOME/share/postgrsql/postgresql.conf.sample') sprintf_s('$PGDATA/postgresql.conf') writefile('$PGDATA/postgresql.conf') InitUndoSubsystemMeta bootstrap_template1 write_version_file setup_auth get_set_pwd setup_depend load_plpgsql setup_sysviews setup_description ... setup_privileges setup_schema setup_update vacuum_db make_template0 make_postgres

February 26, 2025 · 1 min · 51 words · Me

PostgreSQL 2-1 Parse

1 语法解析概述 1.1 语法解析的目的 语法解析的目的 用户向数据发送以下SQL语句时: CREATE TABLE t1 (c1 INT, c2 TEXT); INSERT INTO t1 VALUES (1, 'data1'); DELETE FROM t1 WHERE c1 = 1; 从用户的角度,掌握SQL语法后,我们很容易理解上述SQL的含义。 从PostgreSQL的角度,上述语句知识一串字符串,需要根据SQL语法的规则,从字符串中解析表名、列名、数据等关键信息。 语法解析的流程 此处将语法解析的步骤简要分为以下4个阶段: 定义语法:PostgreSQL开发人员需要根据SQL标准,制定一些类语法规则。比如: 当用户执行CREATE TABLE ..时,表示用户需要创建表 当用户执行CREATE TABLE tablename ..时,表示用户要创建的表名叫tablename 发布语法:PostgreSQL会在官网上发布其定义的各种语法 构造语句:当开发人员想让数据执行某些操作时,需根据数据库定义的语法,构造SQL语句,再让数据库执行。比如: 当用户想创建一个名为t1的表,需要构造SQL语句CREATE TABLE t1 .. 解析语法:PostgreSQL接收SQL语句后,根据语法规则,可解析SQL想要执行什么操作,生成1个结构体,结构中存储了SQL语句的关键信息,比如: 处理CREATE TABLE t1 ..,结构体中,将有1个变量表示表名,该变量的值将被复制为t1 执行语法:在解析用户操作后,生成一个结构体,即根据结构体,开始执行各种操作 1.2 语法解析的类型 PostgreSQL支持上百种语法,本文主要介绍以下4个常用的语法: CREATE TABLE .. SELECT .. FROM .. INSERT INTO .. DELETE FROM .. 2 解析语法 [ WITH [ RECURSIVE ] with_query [, ...] ] SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] * | expression [ [ AS ] output_name ] [, ...] [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY expression [, ...] ] [ HAVING condition [, ...] ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ] [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ] -- from_item [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ] [ LATERAL ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ] with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ] [ LATERAL ] function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...] | column_definition [, ...] ) ] [ LATERAL ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] ) from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ] -- with_query with_query_name [ ( column_name [, ...] ) ] AS ( select | values | insert | update | delete ) TABLE [ ONLY ] table_name [ * ] 参考 http://www.postgres.cn/docs/9.3/sql-select.html ...

January 21, 2025 · 10 min · 1929 words · Me

PostgreSQL 2-2 Analyze

1 概述 1.1 语义分析的目的 语义分析的目的 上文提到,PostgreSQL接收SQL语句时,会生成1个语法解析树,语法解析树存储了SQL语法中的关键信息。比如,在语法INSERT INTO t1 VALUES(1, 'data1')中,解析结果可说明: 这是一条用于插入数据的INSERT语法 数据将插入t1表中 要插入的数据是(1, 'data1') … 但是,数据库执行时,还需要更多的关键信息才行,比如,在INSERT INTO t1 VALUES(1, 'data1')的语法树中,PostgreSQL需要获取一些关键信息: 数据库中是否有表叫t1 t1表有几列,每列的的数据类型是什么 语法中的值(1, 'data1')是否符合t1表的定义 … 1.2 本文的目标 本文以几个常见且简单的语法为例,介绍语义分析的详细功能 CREATE TABLE .. SELECT .. FROM .. INSERT INTO .. DELETE FROM .. 1.3 语义分析的调用关系 exec_simple_query pg_parse_query pg_analyze_and_rewrite parse_analyze 1.1 整体流程 // 语义分析 exec_simple_query pg_parse_query pg_analyze_and_rewrite parse_analyze transformTopLevelStmt transformOptionalSelectInto transformStmt transformInsertStmt exec_simple_query() pg_parse_query() for (;;): pg_analyze_and_rewrite() Query *query = parse_analyze(Node *parsetree) List *querytree_list = pg_rewrite_query(query) pg_plan_queries() PortalRun() 1.2 分析器 Query *parse_analyze(Node *parseTree) ParseState *pstate = make_parsestate() Query *query = query = transformTopLevelStmt(pstate, parseTree) query = transformStmt(pstate, parseTree) /* 对各种类型语法进行语义分析 */ Query *result switch nodeTag(parseTree) { case T_InsertStmt: result = transformInsertStmt(pstate, (InsertStmt *) parseTree) case T_DeleteStmt: result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree) case T_UpdateStmt: result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree) case T_SelectStmt: SelectStmt *n = (SelectStmt *) parseTree; if n->valuesLists: transformValuesClause(pstate, n) else if n->op == SETOP_NONE: result = transformSelectStmt(pstate, n) case T_DeclareCursorStmt: ... case T_ExplainStmt: ... case T_CreateTableAsStmt: ... default: result = makeNode(Query) result->commandType = CMD_UTILITY result->utilityStmt = (Node *) parseTree } return result; 1.3 SELECT 分析 Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt) Query *qry = makeNode(Query) if stmt->withClause: qry->cteList = transformWithClause(pstate, stmt->withClause) transformFromClause(pstate, stmt->fromClause) qry->targetList = transformTargetList(pstate, stmt->targetList) markTargetListOrigins(pstate, qry->targetList) Node *qual = transformWhereClause(pstate, stmt->whereClause) qry->havingQual = transformWhereClause(pstate, stmt->havingClause) qry->sortClause = transformSortClause(pstate, stmt->sortClause, &qry->targetList) qry->groupClause = transformGroupClause(pstate, stmt->groupClause, &qry->groupingSets, &qry->targetList, qry->sortClause) qry->distinctClause = transformDistinctOnClause(pstate, stmt->distinctClause, &qry->targetList, qry->sortClause) qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset) qry->limitCount = transformLimitClause(pstate, stmt->limitCount) qry->windowClause = transformWindowDefinitions(pstate, pstate->p_windowdefs, &qry->targetList) qry->jointree = makeFromExpr(pstate->p_joinlist, qual) if pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual: parseCheckAggregates(pstate, qry) assign_query_collations(pstate, qry) return qry

January 21, 2025 · 2 min · 256 words · Me

PostgreSQL 2-3 Rewrite

重写功能 -- 创建2个表 CREATE TABLE t1 (c1 INT, c2 TEXT); CREATE TABLE t2 (c1 INT, c2 TEXT); -- 创建1条重写规则 -- 触发条件:向t1表写入数据时 -- 执行操作:将SQL语句重写为:同时向t2写入相同数据 CREATE OR REPLACE RULE r1 AS ON INSERT TO t1 DO ALSO INSERT INTO t2 VALUES (new.c1, new.c2); -- 向t1写入一条数据 INSERT INTO t1 VALUES (1, 'abc'); -- 验证t2也写入了一条数据 SELECT * FROM t2; DROP TABLE t1,t2; 重写规则 语法 定义重写规则的语法如下: CREATE [ OR REPLACE ] RULE name AS ON { SELECT | INSERT | UPDATE | DELETE } TO table_name [ WHERE condition ] DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) } 约束 ...

February 5, 2025 · 2 min · 233 words · Me

PostgreSQL 2-4 Plan

SQL 引擎 1 概述 1.1 生成计划的目的 上文提到,在语法分析、语义分析之后,PostgreSQL已获取执行所需的详细信息。计划生成主要针对一些复杂的SQL语句,主要是SQL语句,计划器主要告诉PostgreSQL,如何更高效地执行复杂的SQL语句: 示例1 假设,有1个表,表上有1个索引,表中有1000万条数据 CREATE TABLE t1 (c1 INT, c2 TEXT); CREATE INDEX i1 ON t1(c1); INSERT INTO t1 .. -- 假设1000万条数据 当用户执行以下SQL语句时,数据库需要从t1表中,依次扫描所有的数据,此时,索引并没有什么作用: SELECT * FROM t1; 当用户执行以下数据时,数据有2种执行方案: 语句 SELECT * FROM t1 WHERE c1 = 10000; 方案1:依次扫描t1表所有数据,然后找到c1=10000的几行 方案2:先扫描索引i1,找到c1=10000的几行数据所在的位置,再去t1表中指定位置读取数据 显然,上述示例中,方案2的执行速度更快,数据库需要根据一定的策略,选择哪种执行方案。这便是计划器的职责。 1.2 生成计划的场景 SQL语法 CREATE TABLE t1 (c1 INT, c2 TEXT); INSERT INTO t1 VALUES (1, 'data-1'), (2, 'data-2'); ANALYZE; SELECT * FROM pg_statistic WHERE starelid = 't1'::regclass; 1.3 计划的简单表示 1.4 算子的分类 共40个 ...

January 21, 2025 · 9 min · 1765 words · Me
心情不好的时候可以点一下 🐱
×
🤖 Doubao AI ×
Hi! 我是你的技术助手。关于代码、架构或 Bug,随时问我!🚀