数据库启动流程
一些概念
- 常规启动模式下,最先启动的是postmaster线程,postmaster线程作为一切的起始,完成各类模块功能的初始化,拉起一系列子线程,最后postmaster转为守护线程,一直在
ServerLoop()
中负责处理会话连接、线程拉起、信号处理转发等等。
main 函数
初始化用于系统调用的锁。 例如操作环境变量时,使用env_lock保护,还有getpwuid_lock等,在这里被称为系统调用,syscall。
检查'GAUSS_MMAP_THRESHOLD'环境变量。
g_instance的遍历初始化。
knl_instance_init() {
一些内存上下文的初始创建。
一些变量、值的赋值为初始值:
0、null、false等
类实例的初始化一个实例
一段初始内存的申请
一些默认值,如data目录内的文件夹名称等
一些结构的创建:
vec_func_hash:内置函数的哈希表
......
}
又创建了几个内存上下文:增量ckpt的,通信的等。
创建ThreapTopMemoryContext等上下文,并初始化一些内存上下文用法的变量,保证内存上下文可用
t_thrd的遍历初始化
knl_thread_init(MASTER_THREAD) {
和g_instance的差不多,都是一些初始化操作,不过这里的是线程级别的。
}
创建一个fake session。
获取启动程序名称:progname = argv[0]
如果是 ‘gs_encrypt’,则运行encrypt_main。一个不知道干啥的没见过的东西。
初始化plog global mem。(啥玩意,看代码里好像有OBS、HADOOP之类的词汇)
保存处理运行程序的display args。
设置一些程序运行的环境变量。 如LC_之类的东西。
--help、--version退出。
检测root,禁止root运行gaussdb
创建一个gs_signal内存上下文
检查并创建 g_sorted_funcs。一个排序后的builtin函数数组,还创建了一堆func_groups之类的东西
启动模式相关参数:
--boot: AuxiliaryPorcess线程: BootStrapProcessMain(); 不退出
--describe-config: GucInfoMain(); exit
--single: Postgres线程: PostgresMain(); exit
正常启动:Postmaster线程:PostmasterMian(); exit
Postmaster线程: PostmasterMain()
初始化线程信息。如thrd...MyProcPid、MyStartTime等。
创建pm的一些内存上下文
初始化一个alarm功能,一个奇奇怪怪的功能,好像还有参数enable_alarm,和GAUSS_WARNING_TYPE环境变量相关。
加载产品版本控制文件、license控制文件等。
初始化了一些OBS、S3、minizip、cjson的东西
初始化llvm
获取gaussdb的安装位置
InitializeGUCOptions(); 初始化GUC列表,此刻并未在配置文件读取并设置,仅配置了一些默认的或环境变量中可读取的,如PGPORT。
参数解析:
while ((opt = getopt_r(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lM:N:"...))) {
各类启动参数
设置的guc等
}
检查启动模式
处理一堆GUC的东西
InitializePostmasterGUC(); 初始化PM级别的GUC。看注释,当前仅能初始化PM级别的GUC,其他的可能还依赖PM的之类的。
看上去好像没做啥东西,就给几个变量赋值了,解析了DMS的一个节点数量。
InitializeNumLwLockPartitions(); 初始化LW锁。 GUC: num_internal_lock_partitions_str
dss_device_init(); 初始化dss api的hook。
如果是FencedUDF模式,则执行UDF模式。
CheckGUCConflicts(); 检查一堆GUC, 主要是GUC之间有些约束,比如archive_mode=on的话则必须得是wal_level >= archive。
initDSSConf(); 检查DSS的配置,文件是否存在等,覆写那些表示dn文件目录的变量,改成dss的。
检查那些datadir是否存在。
ConfigRecoveryParallelism(); ProcessRedoCpuBindInfo(); 并行回访相关的GUC的计算配置
初始化ROT内存上下文。
读取gaussdb.state,配置点什么。
开启enable_dcf的话,配置一大堆什么全局变量的东西。
alarm的一些啥初始化。
CreateDayaDirLockFile(); 创建postmaster.pid
一堆hook的初始化,有pgaudit、autoexplain、ledger。
process_shared_preload_libraries(); 加载.so。
load_hba(); 加载hba。
根据listen_addersses,创建通信socket,最多可创建64个。还有一些啥玩意ha_listen、Bonjour相关的。还有一个退出回调。
InitDolpinProtoIfNeeded(); 海豚插件的初始化。
开了线程池的话,初始化线程池。
初始化gstrace相关的东西
初始化GlobalBcm,不知道啥功能
reset_shared(); 初始化所有的共享内存。先计算大小,然后统一申请,然后逐个模块的初始化。
BackendArrayAllocation(); 创建一个Backend数组
又初始化了一堆东西。线程池的、后续转入守护线程要用的、HA相关的内存、
PMInitDBStateFile(); 创建gaussdb.state
set_max_safe_fds(); 不知道干啥的
set_stack_base(); 设置函数栈起点,用于后续栈深度检查,防止爆栈。
一些状态文件等的设置,啥postmaster.opts、config_exec_params之类的
写external_pid_file,如果需要的话。?干啥用的
设置一堆信号处理函数。
初始化bbox。
初始化pgstat模块,此处仅初始化一些内存结构,数据文件,并不启动collector线程,线程得等到后续好多模块初始化完成之后才行。
pgstat_init();
GlobalStatsTrackerInit()
一系列乱七八糟功能的初始化,一些内存结构的申请、创建、等等等等:
WML
ABO
GSC
ProcSubXid
Stream
PBE
nodegroup
RoleIdHash
unique sql
gs_stack
hypopg
asp
instr user
opfusion
capture view
percentile
track stmt control
global seq
mem_log dir
启动syslogger线程。guc:LOGGING_COLLECTOR
aio初始化。
alarm线程启动
repareBackend线程启动。(干啥的?没见过)
读取加载ident文件。pg_ident.conf
RemovePgTempFiles(); 删除旧的临时表文件
删除旧的错误缓存文件
初始化mot引擎
enable_dms:
读取控制文件pg_control, 读取一些啥primary id、reform列表之类的。
reform的一些东西
SS_PRIMARY_MODE:
设置dssserver的状态
ENABLE_DSS
初始化dss日志
enable_dcf || enable_dms:
初始化一些啥玩意backend变量
enable_dms:
DMSInit(); 初始化DMS
拉起 DMS AUXILIARY 线程
uwal的一些处理初始化
【共享存储初始化】:
ShareStorageInit();
exrto_standby_read_init();
reform是等个啥玩意启动。否则就【拉起startup线程】
进入ServerLoop()
Postmaster线程:ServerLoop()
这是postmaster线程的主要循环在这里完成自己的守护工作。主要是处理分配接入的会话并拉起pg线程、处理各类子线程的请求、处理转发信号等。