Chapter 7. 管理数据库
Table of Contents
7.1. 概述
7.2. 创建数据库
7.3. 模板数据库
7.4. 数据库配置
7.5. 变更位置
7.6. 删除数据库
每个正在运行的PostgreSQL服务器实例都管理着一个或多个数据库。 因此,在组织SQL("数据库对象")对象的层次中,数据库位于 最顶层。本章描述数据库的属性,以及如何创建,管理,和删除它们。
7.1. 概述
数据库是一些SQL对象("数据库对象")的命名集合; 通常每个数据库对象(表,函数等等)属于并且只属于一个数据库. (不过有几个系统表,比如 pg_database,属于整个安装 并且可以在安装之内的每个数据库里访问.) 更准确地说,一个数据库是一个模式的集合,而模式包含表,函数等等。 因此完整的层次是这样的:服务器,数据库,模式,表(或者表以外的其他 什么东西)。
一个与数据库服务器联接的应用应该在它的联接请求里面带有它想与之联接 的数据库名称.不允许在一次联接里面对多个数据库访问.(不过 没有限制一个应用与同一个或者其他数据库可以建立的联接数量.) 不过,我们可以从同一个联接中访问多个模式。模式只是纯逻辑的概念, 谁能访问什么东西是由权限系统管理的。数据库是物理上相互隔离的, 对它们的访问控制是在联接层次进行控制的。如果一个PostgreSQL 服务器实例用于承载那些应该分隔并且相互之间并不知晓的用户和 项目,那么我们建议把它们放在不同的数据库里。如果项目或者用户 是相互关联的,并且可以相互使用对方的资源,那么应该把它们放 在同一个数据库里,并且可能是不同的模式里。有关管理模式的更多 信息在 PostgreSQL 7.3 用户手册 里。
注意: SQL 把数据库称作"目录",不过这两个东西实际上 没有什么区别.
7.2. 创建数据库
为了创建和删除数据库, 必须先运行PostgreSQL服务器(参阅 Section 3.3).
数据库是用查询语言命令CREATE DATABASE创建的: CREATE DATABASE:
CREATE DATABASE name
这里的 name 遵循SQL标识符的一般规则. 当前用户自动成为此新数据库的所有者.同时,以后删除这个数据库 也是这个用户的特权(同时还会删除其中的所有对象,即使那些对象 有不同的所有者也一样.)
创建数据库是一个有限制的操作.参阅 Section 6.2 获取如何赋权限的信息.
因为你需要与数据库服务器联接才能执行命令 CREATE DATABASE, 那么还有一个问题是任意节点的第一个数据库是怎样创建的? 第一个数据库总是由initdb命令在初始化数据存储区的时候 创建的.(参阅Section 3.2.)通常这个数据库叫 template1而且不能被删除. 因此要创建第一个"真正"的数据库的时候 你可以与template1联接.
"template1"的名字可不是随便取的,当创建一个新的数据库时, 实际上就是克隆了(复制)了模板数据库. 这就意味着你对template1做的任何修改都会传播到所有 随后创建的数据库.这就意味着说你不能把模板数据库用于真正的工作中, 但是如果明智地使用这个特性,那它可以带来许多方便.更多细节见 Section 7.3. (译注:比如增加用户定义函数等等.)
另外,为了更方便一些,你还可以用一个 shell 脚本来创建新数据库, createdb.
createdb dbname
createdb 没变什么魔术,它和 template1 联接并执行 CREATE DATABASE 命令. 和上面介绍地完全一样.它在内部使用 psql 程序. createdb 的手册页包含使用它的细节.尤其是不带任何参数调用 createdb 将以当前用户名为名称创建数据库, 这可能是也可能不是你要的.
注意: Chapter 4 包含有关如何限制某个用户 可以连接的数据库的信息。
有时候你想为其他什么人创建一个数据库。那个用户应该成为新数据库的 所有者,这样他就可以自己配置和管理这个数据库。要实现这个目标, 使用下列命令中的某一条:
CREATE DATABASE dbname OWNER username;
上面的是在 SQL 环境中,或者是
createdb -O username dbname
要想为其他用户创建一个数据库,你自己必须是数据库的超级用户。
7.3. 模板数据库
CREATE DATABASE 实际上是通过拷贝一个现有的数据库进行工作的. 缺省时,它拷贝名字叫 template1 的标准系统数据库. 所以该数据库是创建新数据库的"模板".如果你给 template1 增加对象,这些对象将被拷贝到随后创建的 用户数据库中.这样的行为允许节点对数据库中的标准套件进行修改. 比如,如果你把过程语言 PL/pgSQL 安装到 template1 里,那么你在创建用户数据库的时候它们就会 自动可得,而不需要额外的动作.
系统里还有第二个标准的系统数据库,叫 template0. 整个数据库包含和 template1 一开始时一样的数据内容, 也就是说,只有你使用的版本的 PostgreSQL 标准的对象.在 initdb 之后,我们不应该对 template0 做任何修改.通过告诉 CREATE DATABASE 使用 template0 而不是 template1 进行拷贝, 你可以创建一个"纯净"的用户数据库,它不会包含任何 template1 里节点所特有的东西. 这一点在恢复 pg_dump 转储的时候是非常方便的∶ 转储脚本应该在一个纯洁的数据库中恢复以确保我们创建了被转储出的数据库 中的正确内容,而不和任何现在可能已经存在在 template1 中的附加物相冲突.
要通过拷贝 template0 的方法创建一个数据库, 使用
CREATE DATABASE dbname TEMPLATE template0;
这条命令是在 SQL 环境里的,或者是在 shell 里
createdb -T template0 dbname
我们可以创建额外的模板数据库,而且实际上我们可以在一个安装中 通过将 CREATE DATABASE 的模板声明为相应的数据库名 拷贝任何数据库.不过,我们必需明白,这个功能并非 一般性的"COPY DATABASE"工具.实际上, 在拷贝操作的过程中,源数据库必需是空闲状态(没有正在处理的数据修改 事务).CREATE DATABASE 在操作开始时将会检查确保没有后端进程 (除它自己以外)与源数据库联接,但是这样并不能保证在拷贝过程中不会发生 修改的事情,如果发生这些事情,那么会导致一个不一致的结果数据库. 因此,我们建议那些用做模板的数据库应该当做只读库对待.
在 pg_database 里有两个有用的标志可以用于 每个数据库∶字段 datistemplate 和 datallowconn.datistemplate 表示该数据库是准备用做 CREATE DATABASE 的模板的. 如果设置了整个标志,那么该数据库可以由任何有 CREATEDB 权限的用户克隆;如果没有设置,那么只有超级用户和该数据库的所有者可以 克隆它.如果 datallowconn 为假,那么将不允许 与该数据库发生任何新的联接(不过现有的会话不会因为把该标志设置为假 而被杀死).template0 数据库通常被标记为 datallowconn = false 以避免对它的 修改.template0 和 template1 都应该总是标记为datistemplate = true.
完成模板数据库的准备之后,或者对某个数据库做了任何标记修改之后, 在该数据库中执行一次 VACUUM FREEZE 或 VACUUM FULL FREEZE 是一个好主意. 如果做这些的时候在同一个数据库中没有其它打开的事务,那么系统 保证在数据库中的元组是"冻结"的,并且不会受事务 ID 重叠的 影响.这个动作对哪些 datallowconn 设置为假的 数据库特别重要,因为在这样的数据库上没有办法做日常维护性的 VACUUM. 参阅 Section 8.2.3 获取更多信息.
注意: template1 和 template0 没有任何特殊的状态, 除了 template1 这个名字是 CREATE DATABASE 以及各种象 createdb 这样的程序的缺省源数据库名之外. 比如,我们可以删除 template1,然后从 template0 中创建它而不会有任何不良效果.如果我们不小心在 template1 里加了一堆垃圾,那么我们就会建议做这样的操作.
7.4. 数据库配置
回顾一下 Section 3.4,我们知道PostgreSQL 服务器提供了大量的运行时配置变量。你可以为许多这样的变量设置 数据库相关的缺省数值。
比如,如果由于某种原因,你想关闭某个数据库上的 GEQO 优化器,你就不得不要么在一开始就在所有数据库中关闭它,要么 是保证每个连接过来的客户端都很小心地发出了 SET geqo TO off; 命令。要令这个设置成为缺省,你可以执行下面的命令
ALTER DATABASE mydb SET geqo TO off;
这样将保存该设置(但不是立即设置它),这样在随后的连接中它将表现出 像在会话开始后马上调用了 SET geqo TO off;的性质。 请注意用户仍然可以在该会话中更改这个设置;它只是缺省。要撤消这样的 设置,使用 ALTER DATABASE dbname RESET varname;.
7.5. 变更位置
我们可以不在缺省位置创建的数据库.请注意所有数据库访问发生在数据 库服务器后端,因此声明的任何位置必须可以被后端访问.
可选数据库位置是通过环境变量引用的,环境变量里给出你想用的 存储位置的绝对路径.这个环境变量必须出现在服务器的环境里, 因此必须在后端启动之前定义.(这样,可选位置就可以在节点管理员的 控制之下;而普通用户则无法修改它.) 任何有效 的环境变量名都可以用于引用一个可选路径,尽管我们建议使 用带有PGDATA前缀的环境变量名以避免和其他变量混淆或冲突。
要在服务器进程的环境里定义环境变量,你必须先停止服务器,然后定义变量, 初始化数据区,最后重新启动服务器. (参阅Section 3.6 和 Section 3.3.) 要设置环境变量,在 Bourne shell 系列里面键入
PGDATA2=/home/postgres/data
export PGDATA2
或者是在csh或tcsh里面键入
setenv PGDATA2 /home/postgres/data
你必须确保这些环境变量总是在服务器环境中存在,否则你就不能 访问数据库.因此你可能会希望把它们设置在 shell 启动脚本文件 或者服务器启动脚本里.
要使用环境变量PGDATA2创建数据存储区,确信 内容目录,(在这里是/home/postgres) 已经存 在并且可以被启动服务器的用户帐户写 (参阅 Section 3.1)。然后在命令行上键入:
initlocation PGDATA2
(不是initlocation $PGDATA2)。然后重新启动服务器。
要在新的位置创建一个数据库,使用下面命令
CREATE DATABASE name WITH LOCATION = 'location'
这里 location 是你用的环境变量, 本例中是 PGDATA2.createdb 命令有个选项 -D 做此用途.
在变更的位置创建的数据库可以象其他数据库一样访问和删除.
注意: 也可以直接给 CREATE DATABASE 命令声明一个绝对路径 而不需要定义环境变量.缺省时这是不允许的,因为有安全风险. 要允许这么做,你必须带着 C 预编译宏ALLOW_ABSOLUTE_DBPATHS 编译PostgreSQL.你可以这么干:
gmake CPPFLAGS=-DALLOW_ABSOLUTE_DBPATHS all
7.6. 删除数据库
数据库是用命令 DROP DATABASE 删除的:
DROP DATABASE name
只有数据库的所有者(也就是说,创建数据库的用户)或者超级用户 可以删除数据库. 删除数据库会删除数据库中包括的所有对象.数据库的删除是不可恢复的.
你不能在与目标库联接的时候执行 DROP DATABASE 命令. 不过,你可以和其他数据库联接,包括template1数据库, 这也是你删除 一个集群上的最后一个库的唯一方法.
为了方便,我们写了一个 shell 程序删除数据库:
dropdb dbname
(和createdb不一样,dropdb 没有缺省删除名称为当前用户名 的数据库的设置.)