介绍
PostgreSQL是以加州大学伯克利分校计算机系开发的对象关系型数据库管理系统。
它包括了可以说是目前世界上最丰富的数据类型的支持,其中有些数据类型可以说连商业数据库都不具备, 比如 IP 类型和几何类型等;其次,PostgreSQL 是全功能的自由软件数据库,很长时间以来,PostgreSQL 是唯一支持事务、子查询、外键、触发器、视图、MVCC等众多特性的开源软件。
进程结构
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
日志: 终止任何活动的服务进程。
日志: 归档进程 (PID 4045)退出,退出码是1。
日志: 所有数据库服务进程被终止;数据库重新初始化。
日志: 数据库在正常运行的过程中被突然关闭,时间是 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内部通过表级别锁和行级锁来控制对数据的并发访问。
数据库、架构(模式)、表
-
模式(schema)是对数据库(database)逻辑分割。
得出结论是:数据库是被模式(schema)来切分的,一个数据库至少有一个模式,所有数据库内部的对象(object)是被创建于模式的。用户登录到系统,连接到一个数据库后,是通过该数据库的search_path来寻找schema的搜索顺序,可以通过命令SHOW search_path;具体的顺序,也可以通过SET search_path TO 'schema_name'来修改顺序。
官方建议是这样的:在管理员创建一个具体数据库后,应该为所有可以连接到该数据库的用户分别创建一个与用户名相同的模式,然后,将search_path设置为"$user",
这样,任何当某个用户连接上来后,会默认将查找或者定义的对象都定位到与之同名的模式中。这是一个好的设计架构。 表空间与数据库的关系
数据库创建语句CREATE DATABASE dbname 默认的数据库所有者是当前创建数据库的角色,默认的表空间是系统的默认表空间--pg_default。
为什么是这样的呢?因为在PostgreSQL中,数据的创建是通过克隆数据库模板来实现的。
表空间是一个存储区域,在一个表空间中可以存储多个数据库,尽管PostgreSQL不建议这么做,但我们这么做完全可行。
一个数据库并不知直接存储表结构等对象的,而是在数据库中逻辑创建了至少一个模式,在模式中创建了表等对象,将不同的模式指派该不同的角色,可以实现权限分离,又可以通过授权,实现模式间对象的共享,并且,还有一个特点就是:public模式可以存储大家都需要访问的对象。