PostgreSQL源码分析——initdb

数据库初始化

在安装完数据库后,需要进行初始化数据库操作,对应PostgreSQL数据库中就是需要进行initdb后,才能对数据库进行启动。initdb的过程,其实就是创建数据库实例的过程,生成模板数据库和相应的目录、文件信息,系统表也是在这个阶段生成的。我们想一下,数据库运行都需要什么? 数据库是用来存取数据的,需要有存放数据的目录,执行过程中需要存放WAL日志,需要pg_wal目录存放日志,需要配置文件,最重要的是数据库怎么把一些文件抽象为表,表在数据库中存储形式就是文件,那么怎么对文件进行“解码”呢?那就是系统表,通过系统表,我们知道表中有多少列,每个列是什么类型,有什么约束等等。可以说,系统表是至关重要的。而initdb最重要的事情之一,就是生成系统表。

我们先看一下initdb后,

postgres@slpc:~/pgsql$ ./bin/initdb -D pgdata/
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locales
  COLLATE:  en_US.UTF-8
  CTYPE:    en_US.UTF-8
  MESSAGES: en_US.UTF-8
  MONETARY: zh_CN.UTF-8
  NUMERIC:  zh_CN.UTF-8
  TIME:     zh_CN.UTF-8
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory pgdata ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Asia/Shanghai
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    ./bin/pg_ctl -D pgdata/ -l logfile start

postgres@slpc:~/pgsql$ cd pgdata/ && ls
base           pg_logical    pg_stat      pg_wal
global         pg_multixact  pg_stat_tmp  pg_xact
pg_commit_ts   pg_notify     pg_subtrans  postgresql.auto.conf
pg_dynshmem    pg_replslot   pg_tblspc    postgresql.conf
pg_hba.conf    pg_serial     pg_twophase
pg_ident.conf  pg_snapshots  PG_VERSION
源码分析

PostgreSQL初始化流程:

  1. 编译阶段,由genbki.pl脚本读取系统表定义文件(src/backend/catalog/pg_*.h),生成postgres.bki文件
# genbki.pl
#    Perl script that generates postgres.bki and symbol definition
#    headers from specially formatted header files and data files.
#    postgres.bki is used to initialize the postgres template database.
  1. initdb创建目录
  2. initdb生成template1数据库
  3. 由template1生成template0和postgres数据库

其核心的说明可以参考其代码注释:

/* initdb --- initialize a PostgreSQL installation
 *
 * initdb creates (initializes) a PostgreSQL database cluster (site,
 * instance, installation, whatever).  A database cluster is a
 * collection of PostgreSQL databases all managed by the same server.
 *
 * To create the database cluster, we create the directory that contains
 * all its data, create the files that hold the global tables, create
 * a few other control files for it, and create three databases: the
 * template databases "template0" and "template1", and a default user
 * database "postgres".
 *
 * The template databases are ordinary PostgreSQL databases.  template0
 * is never supposed to change after initdb, whereas template1 can be
 * changed to add site-local standard data.  Either one can be copied
 * to produce a new database.
 *
 * For largely-historical reasons, the template1 database is the one built
 * by the basic bootstrap process.  After it is complete, template0 and
 * the default database, postgres, are made just by copying template1.
 *
 * To create template1, we run the postgres (backend) program in bootstrap
 * mode and feed it data from the postgres.bki library file.  After this
 * initial bootstrap phase, some additional stuff is created by normal
 * SQL commands fed to a standalone backend.  Some of those commands are
 * just embedded into this program (yeah, it's ugly), but larger chunks
 * are taken from script files.

现在我们分析一下initdb的源码,核心代码在src/bin/initdb/initdb.c中, 源码的解析可以参考《PostgreSQL数据库内核分析》第2章。

main(int argc, char *argv[])
--> atexit(cleanup_directories_atexit);    // 如果执行失败,清除已创建的目录文件
--> setup_pgdata();                     // 获取PGDATA目录,或从-D 中获取
--> setup_data_file_paths();        
--> initialize_data_directory();
    --> create_data_directory();        // 创建PGDATA目录
    --> create_xlog_or_symlink();       // 创建pg_wal目录
    --> mkdir(path, pg_dir_create_mode) //创建其他的目录,base,global, pg_xact等等
    --> write_version_file(NULL);       // 创建PG_VERSION文件,写入主版本号, 数据库启动时会检查应用程序与实例版本好是否兼容
    --> set_null_conf();                // 创建配置文件postgresql.conf
	--> test_config_settings();
	--> setup_config();                 // 写配置文件,postgresql.conf pg_hba.conf postgresql.auto.conf
    --> bootstrap_template1();          // run the BKI script in bootstrap mode to create template1,数据存储在base/1中
        --> snprintf(cmd, sizeof(cmd), "\"%s\" --boot -x1 -X %u %s %s %s %s", backend_exec, wal_segment_size_mb * (1024 * 1024), data_checksums ? "-k" : "", boot_options, extra_options, debug ? "-d 5" : "");
        --> PG_CMD_OPEN;
        	for (line = bki_lines; *line != NULL; line++)
	        {
		        PG_CMD_PUTS(*line);
		        free(*line);
	        }
        --> PG_CMD_CLOSE;

    --> write_version_file("base/1");
    --> setup_auth(cmdfd);
	--> setup_run_file(cmdfd, system_constraints_file);
	--> setup_run_file(cmdfd, system_functions_file);
	--> setup_depend(cmdfd);
    --> setup_run_file(cmdfd, system_views_file);
    --> load_plpgsql(cmdfd);            // load PL/pgSQL server-side language
	--> vacuum_db(cmdfd);
	--> make_template0(cmdfd);
    -->	make_postgres(cmdfd);

创建数据库其实并不是initdb独立去完成的,只是initdb向Postgres进程发送命令,由postgres进程通过--boot进入特殊的bootstrap模式运行执行。bootstrap_template1,这个比较重要,主要是启动postgres进程,执行postgres.bki中特殊的语句,创建系统表。这里说明一下,PG_CMD_OPENPG_CMD_PUTSPG_CMD_CLOSE是什么意思:

#define PG_CMD_OPEN \
do { \
	cmdfd = popen_check(cmd, "w"); \
	if (cmdfd == NULL) \
		exit(1); /* message already printed by popen_check */ \
} while (0)

/* Open a subcommand with suitable error messaging */
static FILE * popen_check(const char *command, const char *mode)
{
	FILE	   *cmdfd;

	fflush(stdout);
	fflush(stderr);
	errno = 0;
	cmdfd = popen(command, mode);
	if (cmdfd == NULL)
		pg_log_error("could not execute command \"%s\": %m", command);
	return cmdfd;
}

实质是调用popen函数去执行指定的命令。

最后,借用阿里云的分享文档,已加深大家对此的理解。详细文档见PostgreSQL体系结构。

image.png

参考文档:
《PostgreSQL数据库内核分析》 第2章
《openGauss数据库源码解析》 第3章

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue大作业-端午节主题网站

vue大作业-端午节主题网站介绍 端午节,又称为龙舟节,是中国的传统节日之一,每年农历五月初五庆祝。这个节日不仅是纪念古代爱国诗人屈原的日子,也是家人团聚、共享美食的时刻。今天,我们非常高兴地分享一个以端午节为…

如何完美解决 Oracle Database 19c 安装程序 - 第7步(共8步)卡住,半小时都不动

🚀 如何完美解决 Oracle Database 19c 安装程序 - 第7步(共8步)卡住,半小时都不动 摘要 在安装 Oracle Database 19c 时,很多用户会在第7步(共8步)遇到卡住的问题,尤其是安装程序长…

【html】用html5+css3+JavaScript制作一个计数器

目录 简介: 效果图: 源码: html: CSS: JS: 源码解析: 简介: 在日常生活当中很多事情都需要用到计数器特别是在体育运动当中,可以我们那么我们可不可以通过网页来制作一个计数器呢答案是肯定的我们需要利…

【Python】Redis数据库

Redis数据库 Unit01一、Redis1.1 概述1.2 安装1.3 Redis-cli1.4 数据类型1.5 字符处理1.6 键的命名规则 二、通用命令三、字符串(String)3.1 概述3.2 常用命令3.3 应用场景 四、列表(List)4.1 概述4.2 常用命令 五、集合(SET)5.1 概述5.3 常用命令 六、有序集合6.1 概述6.2 常用…

智慧养老,乐享晚年 — 探索新时代的养老模式

​随着科技的飞速发展和人口老龄化趋势的加剧,传统的养老模式已经无法满足现代社会的需求。人们期待在晚年能够享受到更加智能、便捷、舒适的生活。智慧养老,作为一种融合现代科技与养老服务的新型模式,正逐渐成为时代的选择,为老…

java第二十五课 —— 多态

多态 传统的方法带来的问题是什么?如何解决?问题是:代码的复用性不高,而且不利于代码维护。 未使用多态时候的例子: Poly01.java: package com.hspedu.poly_;public class Poly01 {public static void main(Strin…

【CT】LeetCode手撕—236. 二叉树的最近公共祖先

目录 题目1- 思路2- 实现⭐236. 二叉树的最近公共祖先——题解思路 3- ACM实现 题目 原题连接:236. 二叉树的最近公共祖先 1- 思路 模式识别 模式1:二叉树最近公共祖先 ——> 递归 判断 递归思路,分情况判断: 1.参数及返…

Linux系统OpenSSH_9.7p1升级详细步骤

版本说明 当前内核版本如下 当前操作系统版本如下 当前OpenSSH版本和OpenSSL版本如下 升级说明 openssh依赖于openssl和zlib,而openssl依赖于zlib,所以我们要先安装zlib,然后是openssl,最后是openssh。zlib-1.3.1下载地址&#…

Folly,一个强大的C++库

目录 1.引言 2.Folly库的特点 3.Folly库的应用场景 4.示例代码 5.总结 1.引言 Folly 是Facebook开发的一个开源、无许可(Apache 2.0)的现代C库,旨在提升性能和简化编写复杂任务的工作流程。它包含了一系列用于系统级编程的工具&#xff…

白蚁监测装置:支持北斗定位

TH-BY2白蚁监测控制管理系统原理 采用白蚁喜欢吃的食物做诱饵,吸引白蚁取食,取食过程中触动报警装置。报警装置发出信号,通过物联网传输到监控系统,经过数据处理,监测结果呈现给用户。用户通知白蚁防治专业人员&#x…

618数码好物有哪些?热门榜单强势出炉

大家好!随着6.18购物狂欢节的来临,我可以明白在面对非常吸引人的商品时,“选择困难症”就上来了。因此,为了帮助大家在这场购物盛事中有方向,我特意结合个人使用体验和市场研究,为大家筛选了几件既具有超高…

CSP-J/S初赛01 计算机概述和计算机硬件系统

第1节 计算机概述 1.1 计算机的发展 代别 年代 逻辑(电子)元件 第一代 1946-1958 真空电子管 第二代 1959-1964 晶体管 第三代 1965-1970 集成电路 第四代 1971-至今 大规模、超大规模集成电…

Einops 张量操作快速入门

张量,即多维数组,是现代机器学习框架的支柱。操纵这些张量可能会变得冗长且难以阅读,尤其是在处理高维数据时。Einops 使用简洁的符号简化了这些操作。 Einops (Einstein-Inspired Notation for operations)&#xff…

HTTP 415错误状态码

HTTP 415错误状态码是指"Unsupported Media Type"(不支持的媒体类型)。这通常发生在客户端向服务器发送请求时,请求中包含的媒体类型(例如Content-Type头部)不被服务器支持或识别的情况下。 解决方法&#…

Erpnext安装

Erpnext安装 环境要求 Ubuntu 23.04 x86_64 Python 3.10.12 pip 23.0.1 node v18.16.0 npm 9.5.1 yarn 1.22.22 MariaDB 10.11.2 Redis 7.0.8 wkhtmltox 0.12.6.1 bench 5.22.6环境安装 Reids 安装 // 安装7.0.8 也可不指定版本 直接执行 sudo apt install redis-server s…

XX集团网上客户管理系统投标书技术部分(358页WORD)

方案介绍:针对客户不断增加的便民查询,业务受理等实际需求,我们将积极整合国内外人才、技术、产品资源,打造XX最便捷的网上处理平台。在平台建设和运营基础上,持续探索各种创新模式,发展多种有针对性的衍生…

攻防演练“轻装上阵” | 亚信安全信舱ForCloud 打造全栈防护新策略

网络世界攻防实战中,攻击风险已经从代码到云横跨全栈技术点,你准备好了吗 云服务器,攻击众矢之的 2022年超过38万个Kubernetes API服务器暴露公网,成为攻击者目标。云服务器,尤其是开源设施,一直以来不仅是…

拐点 万维钢电子书(拐点万维钢下载在线阅读)

本文节选自《拐点万维钢》在线阅读 医院急诊室有个特别常见的状况是病人胸口痛。对这种情 况,医生必须判断是不是心脏病,是心脏病就得赶紧处置。但问题 是,急诊医生并没有很好的诊断方法。 通常的做法是搞个正式的检查,而心脏病检…

碳课堂 | 手把手教你申报CBAM

CBAM全称为 Carbon Border Adjustment Mechanism,也被称作“碳关税”或“碳边境调节机制”,是指在实施国内严格气候政策的基础上,要求进口或出口的高碳产品缴纳或退还相应的税费或碳配额。目前,由于欧盟碳边境调节机制是全球第一个…

示例:WPF中在没有MouseDoubleClick的控件中如何识别双击

一、目的&#xff1a;由于MouseDoubleClick控件是在Control中实现&#xff0c;那么在底层控件如Grid中想要类似功能如何实现&#xff0c;这里通过MouseDown的事MouseButtonEventArgs参数去实现 二、实现 定义Grid并注册Grid的MouseDown事件 <Grid Background"Transpa…