Postgresql与Oracle类似,是多进程结构的数据库,各种不同类型的进程相互协作,完成客户端的操作请求,同时保证数据的完整性与一致性。
Postgresql数据库中主要有两类进程,第一类是backend进程,第二类是数据库后台进程。Backend进程负责接收和执行客户端发出的命令请求(sql命令、函数调用等操作)。客户端每发出一个连接请求,数据库都会创建一个新的backend进程来为客户端服务。该backend进程会一直存在,直到客户端主动关闭数据库连接或者遇到异常而结束运行。
(1)postmaster 进程
负责在启动数据库的时候创建共享内存并初始化各种内部数据结构,如锁表,数据库缓冲区等,该进程在数据库中只有一个。在数据库启动以后负责监听用户请求,创建Backend进程来为用户服务。
(2)vacumm控制进程和vacuum工作进程
这两类进程与Postgresql的并发控制机制有关。vacuum工作进程负责清除数据库中无用的历史数据(已经被删除或更新的记录),同时更新查询优化器的统计信息,确保产生可以接受的查询计划。vacumm控制进程负责监控数据库的运行状态,动态地创建 vacuum工作进程来执行相应的任务。
(3)后台写数据库进程
负责将数据缓冲区中已被更新的数据写入数据库物理数据文件中。
(4)归档进程
负责将系统产生的事务日志文件复制到其他外部存储介质中。
(5)写事务日志进程
负责将系统产生的事务日志写到事务日志文件中。
(6)统计数据收集进程
负责收集数据库运行中的统计信息,如一个表上面进行了多少次插入与更新操作。
Postgresql各个进程之间的通信机制主要是操作系统共享内存。数据缓冲区、redo log缓冲区和锁表等结构都存放在共享内存里面。
Postgresql数据库与客户端的通信方式是TCP/IP协议(支持IPV4、IPV6和SSL)。如果客户端与数据库运行在同一台机器上,它们之间还可以通过Unix domain socket通信。
在Postgresql中,一个Backend进程崩溃后, Postmaster进程会终止所有的数据库进程,恢复数据库,然后重新打开数据库。在数据库的日志文件中会出现类似以下的信息:
日志: 数据库Backend进程 (PID 4056) 被信号9终止: Killed
日志: 终止任何活动的服务进程。
日志: 数据库在正常运行的过程中被突然关闭,时间是 2008-12-09 21:07:45 CST。
日志: 发现长度为0的redo记录,位于 0/20000120
日志: 不需要应用redo记录到数据库中。
日志: 自动vacuum控制进程已启动。
日志: 数据库已经准备好接受用户连接请求。
这样做是因为Postgresql数据库的多个进程通过共享内存通信,每个服务进程都可以访问和修改核心的数据结构。一个服务进程在崩溃以前可能错误地修改了某些共享的数据结构,其它的服务进程若继续执行,可能使某些数据处于不一致的状态。所以系统自动关闭数据库,恢复数据库以后后重新打开它。
物理存储
Postgresql中每个表和表上定义的索引的数据都存放在一个或多个操作系统文件中。一个数据文件只能存放一个表或索引中的数据。在32位操作系统上,如果表或索引文件的大小超过1GB,数据库将会创建新的操作系统文件来存放数据。
Postgresql数据文件由多个数据页组成,每个数据页的大小固定为8KB。一条记录只能存放在一个数据页中,不能横跨多个数据页。当一条记录过长而无法在一个数据页内被存储时,系统将会使用一种叫TOAST 的技术来存储这条记录。数据文件的大小由数据库自动控制,用户不能调整数据文件的大小。
Postgresql中也有表空间的概念,用户创建表时,可以指定存放该表的表空间。Postgresql的表空间与其它数据库中的表空间的实现方式是不同的。Postgresql的表空间只是一个文件系统目录名,通过将不同的物理磁盘mount到不同的表空间上,就可以控制数据库对象的物理存储分布,从而达到IO负载均衡的目的。
并发控制
Postgresql用的是多版本并发控制机制(Multiversion concurrency control),它的特点在于读操作在数据库中不会产生锁,读操作不影响 写操作,写操作不影响读操作。只有在两个或多个事务试图同时更新同一条记录时才会有等待出现。这种机制可以减少数据库中的锁竞争情况,提高数据库的吞吐量。
在Postgresql中,数据库当前数据与历史数据位于同样存储结构中,事务通过每条记录的tmin于tmax系统属性来判断当前记录是否对自己可见,当一条记录被删除或更新时,不会立即从数据库中被除去,因为可能有正在运行的事务需要它,以后系统会通过vacuum进程来回收这些记录占有的存储空间。
Postgresql提供两种事务隔离级别Read Committed 和Serializable这两种事务隔离级别都是符合sql标准的, 同时支持savepoint功能。 Postgresql内部通过表级别锁和行级锁来控制对数据的并发访问。
查询优化
Postgresql使用的是基于成本的优化器(Cost based optimizer)。理论上基于成本的优化器会计算用户输入的查询语句的每个合法的查询计划的执行成本,然后从中选择成本最小的计划作为执行查询语句的最终计划。 在实际应用中,查询语句的合法的查询计划的个数是随查询复杂度的增加呈指数增长的。对于过于复杂查询,如果遍历每个合法的查询计划,将会消耗掉大量的时间,这是不能被用户接受的,所以优化器不会遍历每个合法的查询计划,只会选择一部分查询计划,从中找到执行成本最小的计划。
备份与恢复
(1)文件系统级别
这种备份方式需要关闭数据库, 然后将所有的数据库文件复制到存放备份的存储介质上即可。
(2)使用数据库导出和导入工具
Postgresql提供数据库导出工具pg_dump和pg_dumpall,它们可以将单个表或整个数据库中的数据导出到外部文件中。可以通过数据库导入工具来恢复数据库。
(3)联机备份(online backup)
这种备份可以在数据库打开的情况下进行,数据库在备份操作进行的时候可以正常地工作,执行客户端发过来的各种命令。 数据库必须运行在归档模式才能进行联机备份操作。
如果数据库备份是通过联机备份创建的,那么Postgresql还支持时间点恢复(Point- in-Time Recovery),可以将数据库恢复到指定的历史状态。