PostgreSQL内核分析

 

 

PostgreSQL内核分析
闫华 postgres_fan@yahoo.com.cn
1前言
一直都想写关于PostgreSQL实现原理方面的文章,由于这是一个工作量巨大的工作,平时还要工作谋生,很难抽出时间 来写,希望能够坚持下来。PostgreSQL作为历史最悠久的开源数据库 管理系统 ,有关它的详细信息可以到http://www.postgresql.org/ 去查阅,这里不再赘述。在MySQL被Oracle 抓在手中以后,MySQL变得前途未卜,在这种情况下,PostgreSQL显得越发地重要。
PostgreSQL作为脱胎于学术研究的数据库管理系统,源代码结构非常地清晰,易于理解,相比之下,MySQL的代码结构就要乱很多(个人之见,MySQL的粉丝不要喷我)。
PostgreSQL的源代码的规模已经非常地大,文件 众多。初学者如果直接去看代码,必然如坠五里雾中,难以理解,所以我的文章着重讲述源代码背后的实现原理,而不是详细地叙述每个函数的输入输出以及每一行代码的作用。让读者能从宏观上把握系统结构,循着系统的主线去阅读源代码要容易地多。
这将是一系列的连载文章,闲言少叙,让我们先从PostgreSQL的进程结构说起。

2 PostgreSQL进程结构
PostgreSQL与Oracle类似,是多进程结构的数据库。在PostgreSQL中主要有postmaster, postgres, vacuum, bgwriter, pgarch, walwriter, pgstat等进程,下面先简单介绍一下每个进程的作用,然后再详细介绍每个进程的实现原理。

(1)postmaster
   负责在启动数据库的时候创建共享内存 并初始化各种内部数据结构,如锁表,数据库缓冲区等,该进程在数据库中只有一个。在数据库启动以后负责监听用户 请求,创建postgres进程来为用户服务。这一点与Oracle的TNS listener进程类似。

(2)postgres
   负责执行用户发出的所有SQL语句,该进程在数据库中可能有多个, Oracle中叫shadow process。

(3)vacuum
    负责清除数据库中无用的历史数据(已经被删除或更新的记录)。更新优化器的统计信息,确保产生可以接受的查询计划,该进程在数据库可能有多个,Oracle无此种类型进程。

(4)bgwriter
    负责将数据缓冲区中已被更新的数据库写入数据库物理数据文件中, Oracle中对应的进程叫DBWR, 该进程在数据库中只有一个。

(5)pgarch
    负责将系统产生的redo log复制到其他外部存储介质中, Oracle中对应的进程叫Archiver,该进程在数据库中只有一个。

(6)walwriter
    负责将系统产生的redo log 写到redo log 文件中(在pg_xlog目录下), Oracle中对应的进程叫LGWR,该进程在数据库中只有一个。

(7)pgstat
    负责收集数据库运行中的统计信息,如一个表上面进行了多少次插入与更新操作,该进程在数据库中只有一个, Oracle无此种类型进程。

2.1 Postmaster进程
Postmaster进程是PostgreSQL启动以后创建的第一个进程,所有的其他进程都是由Postmaster创建的。与Postmaster进 程相关的大部分代码都在src/backend/postmaster/postmaster.c文件中。Postmaster进程的入口函数是 PostmasterMain。
Postmaster进程在系统启动时首先进行一些初始化工作,创建共享内存和信号量等数据结构,创建pgstat等后台进程,然后调用 ServerLoop函数进入监听客户端连接请求的状态,ServerLoop函数的代码是一个无限循环的结构,正常的情况下,Postmaster进程 永远都不会退出ServerLoop函数。ServerLoop函数的主要功能是在收到客户端连接请求的情况下,创建一个新的postgres进程来为客 户端服务。
因为所有的其他进程都由Postmaster进程创建,所以它们都是Postmaster的子进程。当一个postgres、bgwriter、 walwriter或vacuum进程因为非正常原因崩溃以后,Postmaster进程要进行一些清理工作,释放它们占用的内部资源,或者重新启动这些 进程。postmaster.c中的reaper函数就是负责执行这个任务的。

2.2 Postgres进程
Postgres进程负责执行客户端发出的所有的SQL语句及自定义函数。与Postgres进程相关的代码在src/backend/tcop/postgres.c文件中,Postgres进程的入口函数是PostgresMain。
PostgresMain首先进行一些初始化工作,然后使用语句for (; 进入一个无限循环状态,等待客户端发来命令请求,接受客户端命令,执行客户端命令,将执行结果返回给客户端。
for (; 无限循环体首先调用ReadCommand从客户端读取一条命令,然后根据命令类型,调用相应的处理函数。例如,对于可以直接执行的SQL语句(simple query),命令类型的代码是“Q”,处理代码如下:
case 'Q':                        /* simple query */
                                {
                                        const char *query_string;

                                        /* Set statement_timestamp() */
                                        SetCurrentStatementStartTimestamp();

                                        query_string = pq_getmsgstring(&input_message);
                                        pq_getmsgend(&input_message);

                                        exec_simple_query(query_string);

                                        send_ready_for_query = true;
语句exec_simple_query(query_string)负责解析SQL语句,生成查询计划,执行查询计划,将查询结果返回给客户端。

2.3 Vacuum进程
PostgreSQL使用的是多版本的并发控制机制,历史数据与当前数据都存放在同一个数据库中,当某些历史数据不再有用时,应当把这些历史数据从数据库 中删除掉(这个过程叫vacuum),让这些数据所占的存储空间能够被重新利用,否则数据库所占的存储空间会越来越大,最后会消耗掉所有的物理存储空间, 导致数据库无法继续正常运行。Vacuum进程负责清除无用的历史数据
Vacuum进程分两种。第一种叫Vacuum控制进程,第二种Vacuum工作进程。自动垃圾Vacuum控制进程在数据库中只有一个,数据库启动以后 这个进程就存在,它睡眠一段时间后,就创建一个或多个Vacuum工作进程来进行垃圾收集(Vacuum控制进程不直接创建Vacuum工作进程,而是通 过postmaster进程创建Vacuum工作进程),然后再进入睡眠状态,不断地重复这个循环,每次睡眠的时间由参数 autovacuum_naptime指定。Vacuum工作进程负责真正的垃圾收集工作,参数autovacuum_max_workers控制能够被 同时创建的Vacuum工作进程的个数的最大值。
与Vacuum控制进程相关的大部分代码都在backend/postmaster/autovacuum.c文件中,Vacuum控制进程的入口函数是 AutoVacLauncherMain。AutoVacLauncherMain首先进行一些初始化工作,然后使用语句for (; 进入一个无限循环状态,睡眠一端时间,检查是否需要创建新的Vacuum工作进程,如果需要,通知Postmaser创建新的Vacuum工作进程,然后继续睡眠,不断地重复这个过程。

 

 

http://bbs.chinaunix.net/thread-1805302-1-1.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值