PostgreSQL实战
上QQ阅读APP看书,第一时间看更新

基础篇

第1章 安装与配置基础

本章介绍PostgreSQL起源、安装部署、基本参数配置、服务管理等方面的内容。

1.1 初识PostgreSQL

PostgreSQL是由PostgreSQL社区全球志愿者开发团队开发的开源对象-关系型数据库。它源于UC Berkeley大学1977年的Ingres计划,这个项目是由著名的数据库科学家Michael Stonebraker(2015年图灵奖获得者)领导的。在1994年,两个UC Berkeley大学的研究生Andrew Yu和Jolly Chen增加了一个SQL语言解释器来替代早先的基于Ingres的QUEL系统,建立了Postgres95。为了反映数据库的新SQL查询语言特性,Postgres95在1996年重命名为PostgreSQL,并第一次发行了以PostgreSQL命名的6.0版本,在2005年,PostgreSQL发行了以原生方式运行在Windows系统下的8.0版本。随着2010年PostgreSQL 9.0的发行,PostgreSQL进入了黄金发展阶段,目前,PostgreSQL最新的稳定版是PostgreSQL 10。

PostgreSQL是目前可免费获得的最高级的开源数据库。它非常稳定可靠,有很多前沿的技术特性,并且性能卓越,在数据完整性和正确性方面赢得了良好的声誉。目前主流的云服务提供商如亚马逊云、微软云、腾讯云、阿里云、百度云都提供了PostgreSQL的RDS服务。

提示

PostgreSQL开发者把它拼读为"Post-Gres-Q-L"(发音:`[/ postɡrεs kju: εl/], `),更多人愿意称PostgreSQL为Postgres。有趣的是由于绕口的名字,常有人读错它,下面的网址有一个PostgreSQL社区提供的发音文件:http://www.postgresql.org/files/postgresql.mp3

1.1.1 PostgreSQL的特点

PostgreSQL几乎支持多种操作系统,包括各种Linux发行版及多种UNIX、类UNIX系统以及Windows系统,例如AIX、BSD、HP-UX、SGI IRIX、Mac OS X、Solaris、Tru64。它有丰富的编程接口,如C、C++、Go、Java、Perl、Python、Ruby、Tcl和开放数据库连接(ODBC)的编程接口。

支持广泛的数据类型,数组、json、jsonb及几何类型,还可以使用SQL命令CREATE TYPE创建自定义类型。

支持大部分的SQL标准,可以支持复杂SQL查询、支持SQL子查询、Window Function,有非常丰富的统计函数和统计语法支持;支持主键、外键、触发器、视图、物化视图,还可以用多种语言来编写存储过程,例如C、Java、python、R语言等。

支持并行计算和基于MVCC的多版本并发控制,支持同步、半同步、异步的流复制,支持逻辑复制和订阅,Hot Standby,支持多种数据源的外部表(Foreign data wrappers),可以将其他数据源当作自己的数据表使用,例如Oracle、MySQL、Informix、SQLite、MS SQL Server等。

1.1.2 许可

PostgreSQL使用PostgreSQL License声明,它是类似于BSD或MIT的软件授权许可。由于这个经OSI认证的版权不限制PostgreSQL在商业环境和有版权的应用程序中使用,因此被公认为是灵活和对商业应用友好的。加上有多个公司的支持和源代码版权归公共所有,因此PostgreSQL广泛流行于在自己的产品里嵌入数据库的厂商中,因为厂商不用担心费用、嵌入软件的版权及版权条款的改变。

完整的许可请参考:https://www.postgresql.org/about/licence/

1.1.3 邮件列表和讨论区

PostgreSQL社区有各类邮件列表组,关注这些邮件列表可以获得最新的技术资料,和使用PostgreSQL的用户增进交流,也可以提交自己的问题和想法。PostgreSQL社区还专门为中国的用户定制了pgsql-zh-general中文邮件组。

PostgreSQL用户可通过下面的网址订阅:https://www.postgresql.org/list

1.2 安装PostgreSQL

PostgreSQL数据库几乎支持市面上可见的所有操作系统,并支持32位和64位架构。本书主要基于64位的CentOS 6和PostgreSQL 10讲解,其他平台和版本请参考官方文档。

安装PostgreSQL有多种方法,例如通过yum源安装、下载官方或第三方商业公司提供的二进制包安装、通过源码编译安装。

1.2.1 通过yum源安装

通过yum源安装是最便捷的方式。这需要你的数据库服务器能够连接互联网,或者能够连接到内部网络的yum源服务器。通常数据库服务器都是与公网物理隔离的,所以常见的情况是连接到内部网络的yum源服务器进行安装,这属于运维和安全性相关的话题,这里不展开讨论了,我们以从官方yum源安装为例进行讲解。

1.安装PostgreSQL的repository RPM

访问PostgreSQL官方主页https://www.postgresql.org/download的下载区选择你的服务器操作系统,由于我们使用CentOS,所以这里我们选择“Binary packages”中的“Red Hat family Linux ”;进入链接页面之后,Select version选择“10”, Select platform选择“CentOS 6”, Select architecture选择“x86_64”;选择完成后页面会动态输出安装命令,执行命令安装PostgreSQL的repository RPM:

        [root@pghost1~]$ yum install
        https: //download.postgresql.org/pub/repos/yum/10/redhat/rhel-6-x86_64/pgdg-
              centos10-10-1.noarch.rpm

执行结束后,在/etc/yum.repos.d目录中可以看到名称为pgdg-10-centos.repo的源配置文件。

2.安装PostgreSQL

安装完PostgreSQL的repository RPM后,通过yum的search命令可以看到有很多postgresql10的包:

        [root@pghost1~]$ yum search postgresql10

其中:

❑ postgresql10-debuginfo.x86_64:postgresql10的调试信息,如果需要进行DEBUG,可以安装它,生产环境中一般不需要安装;

❑ postgresql10.x86_64:这个包只包含PostgreSQL的client端程序和库文件,不会安装数据库服务器;

❑ postgresql10-contrib.x86_64:PostgreSQL的附加模块,包括常用的扩展等;

❑ postgresql10-devel.x86_64:PostgerSQL的C和C++头文件,如果开发libpq程序,它是必需的;

❑ postgresql10-docs.x86_64:文档;

❑ postgresql10-server.x86_64:PostgreSQL server端程序,作为数据库服务器,它是最核心的包;

作为专有的数据库服务器来说,通常安装server和contrib两个包就足够了,client包会随它们一起被安装。通过如下命令安装它们:

        [root@pghost1~]$ yum install postgresql10-server postgresql10-contrib

提示

如果使用脚本安装时,可以使用yum的“-y”参数进行安装,这样可以避免安装途中出现确认安装的提示。

          [root@pghost1~]$ yum install -y postgresql10-server postgresql10-contrib

如果网络状况较好,大约几秒钟就可以完成安装。使用官方yum源安装的位置在/usr/pgsql-10目录,可执行文件位于/usr/pgsql-10/bin目录,并且会自动创建一个postgres账户,它的home目录在/var/lib/pgsql。

3.卸载通过yum源安装的PostgreSQL

可执行如下命令,查看已经安装的PostgreSQL软件包:

        [root@pghost1~]$ rpm -qa | grep postgresql
        postgresql10-10.0-1PGDG.rhel6.x86_64
        postgresql10-libs-10.0-1PGDG.rhel6.x86_64
        postgresql10-contrib-10.0-1PGDG.rhel6.x86_64
        postgresql10-server-10.0-1PGDG.rhel6.x86_64

可以使用yum remove命令逐个卸载,最简单粗暴的办法是卸载libs包即可,因为其他几个包都会依赖它,卸载libs包会将其他包一并卸载:

        yum remove postgresql10-libs-10.0-1PGDG.rhel6.x86_64

由于安装的时候已经将PostgreSQL作为服务安装,所以还需要删除服务管理脚本:

        [root@pghost1~]$ rm -f /etc/init.d/postgresql-10

1.2.2 通过源码编译安装

通过源码编译安装PostgreSQL和编译其他的开源工具一样简单方便。

1.下载源码

在PostgreSQL官方主页https://www.postgresql.org/ftp/latest下载区选择所需格式的源代码包下载;

        [root@pghost1~]$ wget https://ftp.postgresql.org/pub/source/v10.0/postgresql-10.0.tar.gz

下载之后解压:

        [root@pghost1~]$ tar -xvf postgresql-10.0.tar.gz

2.运行configure程序配置编译选项

运行configure程序之前,需要先准备好编译环境和安装必要的包:

        [root@pghost1~]$ yum groupinstall "Development tools"
        [root@pghost1~]$ yum install -y bison flex readline-devel zlib-devel

在源代码目录中运行configure --help命令查看支持的配置编译选项:

        [root@pghost1~]$ cd postgresql-10.0
        [root@pghost1~]$ ./configure --help | less

PostgreSQL支持的编译选项众多,常用的编译选项有:

❑ --prefix=PREFIX:指定安装目录,默认的安装目录为“/usr/local/pgsql”。

❑ --includedir=DIR:指定C和C++的头文件目录,默认的安装目录为“PREFIX/include”。

❑ --with-pgport=PORTNUM:指定初始化数据目录时的默认端口,这个值可以在安装之后进行修改(需要重启数据库),修改它只在自行制作RPM包时有用,其他时候意义并不大。

❑ --with-blocksize=BLOCKSIZE:指定数据文件的块大小,默认的是8kB,如果在OLAP场景下可以适当增加这个值到32kB,以提高OLAP的性能,但在OLTP场景下建议使用8kB默认值。

❑ --with-segsize=SEGSIZE:指定单个数据文件的大小,默认是1GB。

❑ --with-wal-blocksize=BLOCKSIZE:指定WAL文件的块大小,默认是8kB。

❑ --with-wal-segsize=SEGSIZE:指定单个WAL文件的大小,默认是16MB。

由于“--with-xxx-size”这4个参数都只能在编译的时候指定,所以在修改它们之前,请提前做好规划和严格的测试,否则后期想再做调整,只能将数据导出重新导入,如果数据量很大会令人抓狂。

运行configure配置编译选项如下所示:

        [root@pghost1 postgresql-10.0]$ ./configure --prefix=/opt/pg10/ --with-pgport=1921
        checking build system type... x86_64-pc-linux-gnu
        checking host system type... x86_64-pc-linux-gnu
        ...
        checking for bison... /usr/bin/bison
        configure: using bison (GNU Bison) 2.4.1
        checking for flex... /usr/bin/flex
        configure: using flex 2.5.35
        ...
        configure: using CPPFLAGS= -D_GNU_SOURCE
        configure: using LDFLAGS=  -Wl, --as-needed
        configure: creating ./config.status
        ...
        config.status: linking src/include/port/linux.h to src/include/pg_config_os.h
        config.status: linking src/makefiles/Makefile.linux to src/Makefile.port

在运行configure程序的过程中,如果遇到类似“configure: error: readline library not found”的错误,说明缺少所需的包或开发包,通过yum进行安装即可。

3.编译安装

在Linux中,PostgreSQL的编译和安装使用GNU make程序,编译使用gmake命令,安装使用gmake install命令。如果希望在编译和安装时,一次性将文档及附加模块全部进行编译和安装,可以使用gmake world命令和gmake install-world命令。对于已经安装的数据库,再单独对文档和附加模块进行编译和安装也是可以的,但仍然推荐使用带有world的编译和安装命令一次做完这些事情,这样可以保证网络中所有数据库软件的一致性,也避免给后期维护工作带来麻烦。

执行gmake或gmake world程序进行编译,如下所示:

        [root@pghost1~]$ gmake

如果使用gmake进行编译,当看到最后一行的输出为“All of PostgreSQL successfully made. Ready to install.”说明已经编译成功。

如果使用gmake world进行编译,当看到最后一行的输出为“PostgreSQL, contrib, and documentation successfully made. Ready to install.”说明已经编译成功。

执行gmake install或gmake install-world程序进行安装,如下所示:

        [root@pghost1~]$ gmake install

如果使用gmake install进行安装,当看到最后一行的输出为“PostgreSQL installation complete.”说明已经成功安装。

如果使用gmake install-world进行安装,当看到最后一行的输出为“PostgreSQL, contrib, and documentation installation complete.”说明已经安装成功。

查看安装的PostgreSQL版本的命令如下所示:

        [root@pghost1~]# /opt/pg10/bin/postgres --version
        postgres (PostgreSQL) 10.0

1.2.3 设置一个软链接

有时候我们为了方便工作,会自己写一些shell或Python脚本处理一些定时任务,经常会通过类似/opt/pg9.x这样的全路径调用一些工具,使用环境变量也会有一些其他的问题存在,如何尽可能地避免这种麻烦?很简单。

创建一个/opt/pgsql的软链接指向当前版本即可,命令如下所示:

        [root@pghost1 opt]$ ln -s /opt/pg10 /opt/pgsql
        [root@pghost1~]$ ll /opt/
        drwxr-xr-x  6 root    root    4096 Oct 11 14:32 pg96
        drwxr-xr-x  6 root    root    4096 Oct 13 17:43 pg10
        lrwxrwxrwx  1 root    root      10 Oct 13 11:25 pgsql -> /opt/pg10/

当进行了版本变更之后,不需要调整大量的脚本,只需要修改这个软链接即可,在下文中我们都会使用它。

1.3 客户端程序和服务器程序

经过上面的安装步骤,已经成功安装了PostgreSQL数据库:

        [postgres@pghost1~]$ tree -L 1 /opt/pgsql/
        /opt/pgsql/
        ├── bin
        ├── include
        ├── lib
        └── share
        4 directories, 0 files

share目录存放着PostgreSQL的文档、man、示例文件以及一些扩展,include目录是PostgreSQL的C、C++的头文件,bin目录就是PostgreSQL的应用程序了。PostgreSQL本身是一个C/S架构的程序,这些应用程序可以分为两类:客户端程序和服务器程序,本章先介绍这些应用程序的功能,并讲解其中比较基础的一部分,其他的会在后续章节详细讲解。

1.3.1 客户端程序

客户端程序也可分为几大类,下面分别介绍。

1.封装SQL命令的客户端程序

clusterdb

clusterdb是SQL CLUSTER命令的一个封装。PostgreSQL是堆表存储的,clusterdb通过索引对数据库中基于堆表的物理文件重新排序,它在一定场景下可以节省磁盘访问,加快查询速度。

举例如下:

        [postgres@pghost1~]$ /opt/pgsql/bin/clusterdb -h pghost1-p 1921-d mydb

reindexdb

reindexdb是SQL REINDEX命令的一个封装。在索引物理文件发生损坏或索引膨胀等情况发生时,可以使用reindexdb命令对指定的表或者数据库重建索引并且删除旧的索引。

举例如下:

        [postgres@pghost1~]$ /opt/pgsql/bin/reindexdb -e -h pghost1-p 1921-d mydb

vacuumdb

vacuumdb是PostgreSQL数据库独有的VACUUM、VACUUM FREEZE和VACUUM FULL, VACUUM ANALYZE这几个SQL命令的封装。VACUUM系列命令的主要职责是对数据的物理文件等的垃圾回收,是PostgreSQL中非常重要的一系列命令。

举例如下:

        [postgres@pghost1~]$ /opt/pgsql/bin/vacuumdb -h pghost1-p 1921 mydb

vacuumlo

vacuumlo用来清理数据库中未引用的大对象。

举例如下:

        [postgres@pghost1~]$ /opt/pgsql/bin/vacuumlo -h pghost1-p 1921 mydb

createdb和dropdb

它们分别是SQL命令CREATE DATABAS和DROP DATABASE的封装。

例如在名为pghost1的主机,端口为1921的实例中创建一个名为newdb的数据库,并且加上注释,命令如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/createdb -h pghost1-p 1921 newdb "New database."

删除名为newdb的数据库的命令如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/dropdb -h pghost1-p 1921 newdb

createuser和dropuser

它们分别是SQL命令CREATE USER和DROP USER的封装。可以通过帮助查看它们的参数说明。

例如创建一个名为newuser的非超级用户,newuser继承自pg_monitor系统角色,只能有1个连接,没有创建数据库的权限,没有创建用户的权限,并且立即给它设置密码,命令如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/createuser -h pghost1-p 1921-c 1-g pg_
            monitor -D -R -S -P -e newuser
        Enter password for new role:
        Enter it again:
        CREATE  ROLE  newuser  PASSWORD  'md518b2c3ec6fb3de0e33f5612ed3998fa4'  NOSUPERUSER
            NOCREATEDB NOCREATEROLE INHERIT LOGIN CONNECTION LIMIT 1 IN ROLE pg_monitor;

是否超级用户、是否允许创建数据库、是否允许创建用户这三个权限可以使用--interactive参数提供交互界面,使用更简单,举例如下:

        [postgres@pghost1~]$ /opt/pgsql/bin/createuser -h pghost1-p 1921-c 1-g pg_
            monitor --interactive -e -P newuser
        Enter password for new role:
        Enter it again:
        Shall the new role be a superuser? (y/n) n
        Shall the new role be allowed to create databases? (y/n) n
        Shall the new role be allowed to create more new roles? (y/n) n
        CREATE  ROLE  newuser  PASSWORD  'md545c93e6e78f597d46a41cfb08dea5ae3'  NOSUPERUSER
            NOCREATEDB NOCREATEROLE INHERIT LOGIN CONNECTION LIMIT 1 IN ROLE pg_monitor;

删除名为newuser的用户的命令如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/dropuser -h pghost1-p 1921 newuser

2.备份与恢复的客户端程序

pg_basebackup取得一个正在运行中的PostgreSQL实例的基础备份。

pg_dump和pg_dumpall都是以数据库转储方式进行备份的工具。

pg_restore用来从pg_dump命令创建的非文本格式的备份中恢复数据。

这部分内容我们在第13章中详细讲解。

3.其他客户端程序

ecpg是用于C程序的PostgreSQL嵌入式SQL预处理器。它将SQL调用替换为特殊函数调用,把带有嵌入式SQL语句的C程序转换为普通C代码。输出文件可以被任何C编译器工具处理。

❑ oid2name解析一个PostgreSQL数据目录中的OID和文件结点,在文件系统章节会详细讲解它。

❑ pgbench是运行基准测试的工具,平常我们可以用它模拟简单的压力测试。

❑ pg_config获取当前安装的PostgreSQL应用程序的配置参数。

❑ PostgreSQL包装了pg_isready工具用来检测数据库服务器是否已经允许接受连接。

❑ pg_receivexlog可以从一个运行中的实例获取事务日志的流。

❑ pg_recvlogical控制逻辑解码复制槽以及来自这种复制槽的流数据。

❑ psql是连接PostgreSQL数据库的客户端命令行工具,是使用频率非常高的工具,在客户端工具一章会专门讲解它的使用。使用psql客户端工具连接数据库的命令如下所示:

            [postgres@pghost2~]$ /opt/pgsql/bin/psql -h pghost1-p 1921 mydb
            psql (10.0)
            Type "help" for help.
            mydb=#

其中的参数含义如下:

❑ -h参数指定需要连接的主机。

❑ -p参数指定数据库实例的端口。

❑ -d参数指定连接哪一个数据库,默认的是和连接所使用的用户的用户名同名的数据库。

连接到数据库之后,就进入PostgreSQL的shell界面,如果是用数据库超级用户连接,提示符由数据库名称和“=#”组成,如果是普通的数据库用户,提示符则由数据库名称和“=>”组成。

使用“\q”或CTRL+D退出,命令如下所示:

        [postgres@pghost2~]$ /opt/pgsql/bin/psql -h pghost1-p 1921 mydb
        psql (10.0)
        Type "help" for help.
        mydb=# \q
        [postgres@pghost2~]$

psql是非常强大的客户端连接工具,功能丰富,在客户端工具一章会对psql做详细讲解。

1.3.2 服务器程序

服务器程序包括:

❑ initdb用来创建新的数据库目录。

❑ pg_archivecleanup是清理PostgreSQL WAL归档文件的工具。

❑ pg_controldata显示数据库服务器的控制信息,例如目录版本、预写日志和检查点的信息。

❑ pg_ctl是初始化、启动、停止、控制数据库服务器的工具。

❑ pg_resetwal可以清除预写日志并且有选择地重置存储在pg_control文件中的一些控制信息。当服务器由于控制文件损坏,pg_resetwal可以作为最后的手段。

❑ pg_rewind是在master、slave角色发生切换时,将原master通过同步模式恢复,避免重做基础备份的工具。

❑ pg_test_fsync可以通过一个快速的测试,了解系统使用哪一种预写日志的同步方法(wal_sync_method)最快,还可以在发生I/O问题时提供诊断信息。

❑ pg_test_timing是一种度量系统计时开销以及确认系统时间绝不会回退的工具。

❑ pg_upgrade是PostgreSQL的升级工具,在版本升级的章节会详细讲解。

❑ pg_waldump用来将预写日志解析为可读的格式。

❑ postgres是PostgreSQL的服务器程序。

❑ postmaster可以从bin目录中看到,是指向postgres服务器程序的一个软链接。

1.4 创建数据库实例

在PostgreSQL中一个数据库实例和一组使用相同配置文件和监听端口的数据库集关联,它由数据目录组成,数据目录中包含了所有的数据文件和配置文件。一台数据库服务器可以管理多个数据库实例,PostgreSQL通过数据目录的位置和这个数据集合实例的端口号引用它。

1.4.1 创建操作系统用户

在创建数据库实例之前要做的第一件事是先创建一个独立的操作系统用户,也可以称为本地用户。创建这个账号的目的是为了防止因为应用软件的BUG被攻击者利用,对系统造成破坏。它拥有该数据库实例管理的所有数据,是这个数据库实例的超级用户。你可以使用你喜欢的用户名作为这个数据库实例超级用户,例如pger等,但通常我们使用postgres作为这个操作系统超级用户的用户名,这个用户将被用来对数据库实例进行start、stop、restart操作。如果使用yum安装,且操作系统中不存在postgres本地用户,安装程序会自动创建名为postgres的操作系统用户和名为postgres的数据库超级用户,尽管如此,仍然建议在yum安装之前预先手动创建postgres用户。

当一个黑客利用一个软件的BUG进入一台计算机时,他就获得了这个软件运行所使用的用户账号的权限。目前我们不知道PostgreSQL是否有这样的BUG,我们坚持使用非管理员账号运行PostgreSQL的目的就是为了减少(万一)黑客利用在PostgreSQL发现的BUG对系统造成的可能损害。

创建系统用户组和用户的命令如下所示:

        [root@pghost1~]$ groupadd -g 1000 postgres
        [root@pghost1~]$ useradd -g 1000-u 1000 postgres
        [root@pghost1~]$ id postgres
        uid=1000(postgres) gid=1000(postgres) groups=1000(postgres)

注意事项:

1)出于安全考虑,这个操作系统用户不能是root或具有操作系统管理权限的账号,例如拥有sudo权限的用户。

2)如果是部署集群,建议配置NTP服务,统一集群中每个节点的操作系统用户的uid和gid,如果集群中某些节点的数据库操作系统用户的uid和gid与其他节点不一致,可以通过groupmod命令和usermod命令进行修改,例如:

        [root@pghost1~]$ groupmod -g 1000 postgres
        [root@pghost1~]$ usermod -u 1000-g 1000 postgres

1.4.2 创建数据目录

接下来,给我们的数据一个安身立命之所,也就是在磁盘上初始化一个数据的存储区域,在SQL标准中称为目录集簇,通常我们也口语化地称它为数据目录。它用来存放数据文件和数据库实例的配置文件,可以把这个目录创建到任何你认为合适的位置。作为数据库专有服务器,一般都会有一个或多个分区来存储数据,通常我们把数据目录放在这样的分区中。

有的时候我们可能会遇到多实例并存的情况,为了区分不同版本的数据,我们通常会建立形如/pgdata/9.x/xxx_data的目录作为数据库实例的数据目录,其中9.x或10为大版本号,xxx_data中的xxx为业务线名称,这样在进行大版本升级或多版本并存、多业务线数据并存的环境下,目录条理更清晰,同时可以减少出错的可能。作为例子,这里我们不考虑多实例并存的情况,创建/pgdata/10/data目录作为数据目录,在data的同级目录创建backups、scripts、archive_wals目录,这几个目录的作用后续章节再详述。创建目录的命令如下所示:

        [root@pghost1~]$ mkdir -p /pgdata/10/{data, backups, scripts, archive_wals}

将数据目录的属主修改为我们创建的操作系统用户,并且修改数据目录的权限为0700。修改目录权限这一步其实并不需要,因为initdb会回收除PostgreSQL用户之外所有用户的访问权限。但我们应该明确知道数据目录包含所有存储在数据库里的数据,保护这个目录不受未授权的访问非常重要。修改权限的命令如下所示:

        [root@pghost1~]$ chown -R postgres.postgres /pgdata/10
        [root@pghost1~]$ chmod 0700 /pgdata/10/data

1.4.3 初始化数据目录

实例化数据目录使用initdb工具。initdb工具将创建一个新的数据库目录(这个目录包括存放数据库数据的目录),创建template1和postgres数据库,初始化该数据库实例的默认区域和字符集编码。initdb命令的语法如下所示:

            [postgres@pghost1~]$ /opt/pgsql/bin/initdb --help
            initdb initializes a PostgreSQL database cluster.
            Usage:
                initdb [OPTION]... [DATADIR]
            Options:
                -A, --auth=METHOD       为本地用户指定pg_hba.conf文件中的认证方法,可以为md5、
                                          trust、password等,为了安装方便,默认的值是trust,但
                                          是除非你信任数据库实例所在服务器上的所有本地用户;
                    --auth-host=METHOD  指定通过TCP/IP连接的本地用户在pg_hba.conf中使用的认证
                                          方法;
                    --auth-local=METHOD指定通过UNIX Socket连接的本地用户在pg_hba.conf文件中的
                                          认证方法;
                [-D, --pgdata=]DATADIR   将要初始化的数据目录;其他选项都可以省略,只有这个选项是必需的;
                -E, --encoding=ENCODING设置数据库的默认编码,实际它是设置了template1的编码,因为
                                          其他新创建的数据库都是以template1为模板克隆的。
                    --locale=LOCALE     设置区域
                    --lc-collate=, --lc-ctype=, --lc-messages=LOCALE
                    --lc-monetary=, --lc-numeric=, --lc-time=LOCALE
                                          为指定的分类设置区域
                    --no-locale         等价于 --locale=C
                    --pwfile=FILE       从一个文件读取第一行作为数据库超级用户的口令。
                -T, --text-search-config=CFG
                                          设置默认的文本搜索配置。
                -U, --username=NAME     设置数据库超级用户的用户名,默认是postgres。
                -W, --pwprompt          在initdb的过程中为数据库超级用户设置一个密码。
                -X, --waldir=WALDIR     指定预写日志(WAL)的存储目录。

知道了这些选项的意义,我们开始初始化上一步创建好的数据目录,如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/initdb -D /pgdata/10/data -W
        The files belonging to this database system will be owned by user "postgres".
        This user must also own the server process.
        The database cluster will be initialized with locale "en_US.UTF-8".
        The default database encoding has accordingly been set to "UTF8".
        The default text search configuration will be set to "english".
        Data page checksums are disabled.
        Enter new superuser password:
        Enter it again:
        fixing permissions on existing directory /export/pg10_data ... ok
        creating subdirectories ... ok
        selecting default max_connections ... 100
        selecting default shared_buffers ... 128MB
        selecting dynamic shared memory implementation ... posix
        creating configuration files ... ok
        running bootstrap script ... ok
        performing post-bootstrap initialization ... ok
        syncing data to disk ... ok
        WARNING: enabling "trust" authentication for local connections
        You can change this by editing pg_hba.conf or using the option -A, or
        --auth-local and --auth-host, the next time you run initdb.
        Success. You can now start the database server using:
            /opt/pgsql/bin/pg_ctl -D /pgdata/10/data -l logfile start
        [postgres@pghost1~]$

因为我们指定了-W参数,所以在初始化的过程中,initdb工具会要求为数据库超级用户创建密码。在initdb的输出中可以看到系统自动创建了template1数据库和postgres数据库,template1是生成其他数据库的模板,postgres数据库是一个默认数据库,用于给用户、工具或者第三方应用提供默认数据库。输出的最后一行还告诉了你如何启动刚才初始化的数据库。

需要注意一点的是:不要在将要初始化的数据目录中手动创建任何文件,如果数据目录中已经有文件,会有如下错误提示:

        initdb: directory "/pgdata/10/data" exists but is not empty
        If you want to create a new database system, either remove or empty
        the directory "/pgdata/10/data" or run initdb
        with an argument other than "/pgdata/10/data".

这样做的目的是为了防止无意中覆盖已有的数据目录。

除了使用initdb来初始化数据目录,还可以使用pg_ctl工具进行数据库目录的初始化,用法如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/pg_ctl init -D /pgdata/10/data -o "-W"

至此,数据库目录初始化完成。

使用官方yum源安装PostgreSQL时会自动创建/var/lib/pgsql/10目录和它的两个子目录:data目录和backups目录。通过service postgresql-10 init命令会初始化/var/lib/pgsql/10/data目录作为数据目录。这样很方便,但是可定制性并不好,建议按照上面的步骤初始化数据目录。

1.5 启动和停止数据库服务器

在使用数据库服务器之前,必须先启动数据库服务器。可以通过service方式、PostgreSQL的命令行工具启动或停止数据库。

1.5.1 使用service方式

启动数据库服务的命令如下所示:

        [root@pghost1~]$ service postgresql-10 start

查看数据库运行状态的命令如下所示:

        [root@pghost1~]$ service postgresql-10 status

停止数据库的命令如下所示:

        [root@pghost1~]$ service postgresql-10 stop

1.5.2 使用pg_ctl进行管理

pg_ctl是PostgreSQL中初始化数据目录,启动、停止、重启、重加载数据库服务,或者查看数据库服务状态的工具,相比service或systemctl的管理方式,pg_ctl提供了丰富的控制选项,执行pg_ctl命令需要操作系统用户使用su命令切换到postgres用户。

1.启动数据库

代码如下所示:

        [root@pghost1~]# su - postgres
        [postgres@pghost1~]$ /opt/pgsql/bin/pg_ctl -D /pgdata/10/data start
        server started

2.查看数据库运行状态

代码如下所示:

        [root@pghost1~]# su - postgres
        [postgres@pghost1~]$ /opt/pgsql/bin/pg_ctl -D /pgdata/10/data status
        pg_ctl: no server running

或者:

        pg_ctl: server is running (PID: 43965)
        /opt/pgsql/bin/postgres "-D" "/pgdata/10/data"

还可以使用pg_isready工具来检测数据库服务器是否已经允许接受连接:

        [postgres@pghost1~]$ /opt/pgsql/bin/pg_isready -p 1921
        /tmp:1921- accepting connections

或者:

        /tmp:1921- no response

3.停止数据库

使用pg_ctl停止数据库的命令为:

        pg_ctl stop     [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]

“-s”参数开启和关闭屏幕上的消息输出;“-t SECS”参数设置超时时间,超过SECS值设置的超时时间自动退出。其中的“-m”参数控制数据库用什么模式停止,PostgreSQL支持三种停止数据库的模式:smart、fast、immediate,默认为fast模式。

❑ smart模式会等待活动的事务提交结束,并等待客户端主动断开连接之后关闭数据库。

❑ fast模式则会回滚所有活动的事务,并强制断开客户端的连接之后关闭数据库。

❑ immediate模式立即终止所有服务器进程,当下一次数据库启动时它会首先进入恢复状态,一般不推荐使用。

在写命令的时候,这三个值可以分别简写为“-ms”“-mf”“-mi”,例如使用smart模式停止数据库的命令如下所示:

        [root@pghost1~]# su - postgres
        [postgres@pghost1~]$ /opt/pgsql/bin/pg_ctl -D /pgdata/10/data -ms stop

1.5.3 其他启动和关闭数据库服务器的方式

还有其他一些启动和停止数据库的方式,例如使用postmaster或postgres程序启动数据库,命令如下所示:

        [root@pghost1~]# su - postgres
        [postgres@pghost1~]$ /opt/pgsql/bin/postgres -D /pgdata/10/data/

这样将在前台运行数据库服务器,通常加上“&”符号让它在后台运行。

在PostgreSQL的守护进程postmaster的入口函数中注册了信号处理程序,对SIGINT、SIGTERM、SIGQUIT的处理方式分别对应PostgreSQL的三种关闭方式smart、fast、immediate。因此我们还可以使用kill命令给postgres进程发送SIGTERM、SIGINT、SIGQUIT信号停止数据库,例如使用smart方式关闭数据库的命令如下所示:

        [postgres@pghost1~]$ kill -sigterm `head -1 /pgdata/10/data/postmaster.pid`
        received smart shutdown request
        shutting down
        database system is shut down

通过日志输出可以看到该命令是通过smart关闭数据库的。它内部的原理可以查看PostgreSQL内核相关的书籍或者阅读源码中pqsignal和pmdie相关的代码进行了解。

因为PostgreSQL的安装程序已经包装好了pg_ctl工具,所以通过kill发送信号的方法一般不常用。

1.5.4 配置开机启动

如果使用官方yum源安装,会自动配置服务脚本;如果通过源码编译安装,则需要手动配置。

1.配置服务脚本

在源码包的contrib目录中有Linux、FreeBSD、OSX适用的服务脚本,如下所示:

        [root@pghost1~]$ ls postgresql-10.0/contrib/start-scripts/
        freebsd  linux  osx

我们将名称为linux的脚本拷贝到/etc/init.d/目录中,将脚本重命名为postgresql-10,并赋予可执行权限,命令如下所示:

        [root@pghost1  ~]$  cp  postgresql-10.0/contrib/start-scripts/linux  /etc/init.d/
            postgresql-10
        [root@pghost1~]$ chmod +x /etc/init.d/postgresql-10
        [root@pghost1~]$ ls -lh /etc/init.d/postgresql-10
        -rwxr-xr-x 1 root root 3.5K Oct 13 16:30 /etc/init.d/postgresql-10

2.设置开机启动

chkconfig --list命令可以查看PostgreSQL是否是开机启动的,如下所示:

        [root@pghost1~]$ chkconfig --list | grep postgresql-10
        postgresql-10   0:off   1:off   2:off   3:off   4:off   5:off   6:off

chkconfig命令将启用或禁用PostgreSQL开机启动,如下所示:

        [root@pghost1~]$ chkconfig postgresql-10 on/off

1.6 数据库配置基础

在一个数据库实例中,有些配置会影响到整个实例,这些我们称为全局配置;有些配置只对一个数据库实例中的单个Database生效,或只对当前会话或者某个数据库用户生效,这一类的配置我们称为非全局配置。

PostgreSQL有两个重要的全局配置文件:postgresql.conf和pg_hba.conf。它们提供了很多可配置的参数,这些参数从不同层面影响着数据库系统的行为,postgresql.conf配置文件主要负责配置文件位置、资源限制、集群复制等,pg_hba.conf文件则负责客户端的连接和认证。这两个文件都位于初始化数据目录中。

1.6.1 配置文件的位置

在实例化数据目录之后,在数据目录的根目录下会有postgresql.conf、postgresql.auto. conf、pg_hba.conf和pg_ident.conf这几个配置文件。除身份认证以外的数据库系统行为都由postgresql.conf文件配置。

1.6.2 pg_hba.conf

pg_hba.conf是它所在数据库实例的“防火墙”,文件格式如下:

        TYPE  DATABASE        USER             ADDRESS                  METHOD
        local database user auth-method [auth-options]
        host database user address auth-method [auth-options]
        hostssl database user address auth-method [auth-options]
        hostnossl database user address auth-method [auth-options]
        host database user IP-address IP-mask auth-method [auth-options]
        hostssl database user IP-address IP-mask auth-method [auth-options]
        hostnossl database user IP-address IP-mask auth-method [auth-options]

这些配置看起来复杂,实际上简单来说每一行的作用就是:允许哪些主机可以通过什么连接方式和认证方式通过哪个数据库用户连接哪个数据库。也就是允许ADDRESS列的主机通过TYPE方式以METHOD认证方式通过USER用户连接DATABASE数据库。

1.连接方式

TYPE列标识允许的连接方式,可用的值有:local、host、hostssl、hostnossl,说明如下:

❑ local匹配使用Unix域套接字的连接。如果没有TYPE为local的条目则不允许通过Unix域套接字连接。

❑ host匹配使用TCP/IP建立的连接,同时匹配SSL和非SSL连接。默认安装只监听本地环回地址localhost的连接,不允许使用TCP/IP远程连接,启用远程连接需要修改postgresql.conf中的listen_addresses参数。

❑ hostssl匹配必须是使用SSL的TCP/IP连接。配置hostssl有三个前提条件:

1.客户端和服务端都安装OpenSSL;

2.编译PostgreSQL的时候指定configure参数--with-openssl打开SSL支持;

3.在postgresql.conf中配置ssl = on。

❑ hostnossl和hostssl相反,它只匹配使用非SSL的TCP/IP连接。

2.目标数据库

DATABASE列标识该行设置对哪个数据库生效;

3.目标用户

USER列标识该行设置对哪个数据库用户生效;

4.访问来源

ADDRESS列标识该行设置对哪个IP地址或IP地址段生效;

5.认证方法

METHOD列标识客户端的认证方法,常见的认证方法有trust、reject、md5和password等。

reject认证方式主要应用在这样的场景中:允许某一网段的大多数主机访问数据库,但拒绝这一网段的少数特定主机。

md5和password认证方式的区别在于md5认证方式为双重md5加密,password指明文密码,所以不要在非信任网络使用password认证方式。

scram-sha-256是PostgreSQL 10中新增的基于SASL的认证方式,是PostgreSQL目前提供的最安全的认证方式。使用scram-sha-256认证方式不支持旧版本的客户端库。如果使用PostgreSQL 10以前的客户端库连接数据库,会有如下错误:

        [postgres@pghost2~]$ /usr/pgsql-9.6/bin/psql -h pghost1-p 1921-U postgres mydb
        psql: SCRAM authentication requires libpq version 10 or above

更多认证方式的详细说明参考官方文档:https://www.postgresql.org/docs/current/static/auth-methods.html

1.6.3 postgresql.conf

postgresql.conf配置文件的文件结构很简单,由多个configparameter = value形式的行组成,“#”开头的行为注释。value支持的数据类型有布尔、整数、浮点数、字符串、枚举,value的值还支持各种单位,例如MB、GB和ms、min、d等。postgresql.conf文件还支持include和include_if_exists指令,并且允许嵌套。

在配置项末尾标记了“# (change requires restart)”的配置项是需要重启数据库实例才可以生效的,其他没有标记的配置项只需要reload即可生效。

1.全局配置的修改方法

修改全局配置的方法有:

❑ 修改postgresql.conf配置文件。

❑ 使用vim、nano类的文本编辑器或者sed命令编辑它们。

❑ 通过ALTER SYSTEM命令修改全局配置,例如:

      mydb=# ALTER SYSTEM SET listen_addresses = '*';

通过ALTER SYSTEM SQL命令修改的全局配置参数,会自动编辑postgresql.auto.conf文件,在数据库启动时会加载postgresql.auto.conf文件,并用它的配置覆盖postgresql.conf中已有的配置。这个文件不要手动修改它。

❑ 启动数据库时进行设置,例如:

        [postgres@pghost1~]$ /opt/pgsql/bin/postgres -D /pgdata/10/data -c port=1922

2.非全局配置的修改方法

❑ 设置和重置Database级别的配置,例如:

        ALTER DATABASE name SET configparameter { TO | = } { value | DEFAULT }
        ALTER DATABASE name RESET configuration

❑ 设置和重置Session级别的配置。

❑ 通过SET命令设置当前Session的配置,例如:

        SET configparameter { TO | = } { value | 'value' | DEFAULT }
        SET configparameter TO DEFAULT;

❑ 更新pg_settings视图,例如:

        UPDATE `pg_settings` SET setting = new_value WHERE name = 'configparameter';
        UPDATE `pg_settings` SET setting = reset_val WHERE name = 'configparameter';

❑ 使用set_config函数更新会话配置,例如:

        SELECT set_config('configparameter', new_value, false);

❑ 设置和重置Role级别的配置,例如:

        ALTER ROLE name IN DATABASE database_name SET configparameter { TO |= } { value
            | DEFAULT }
            ALTER ROLE name IN DATABASE database_name RESET configparameter

3.如何查看配置

查询pg_settings系统表,例如:

        SELECT name, setting FROM pg_settings where name ~ ‘xxx';
        SELECT current_setting(name);

通过show (show all)命令查看。

4.使配置生效的方法

如果是不需要重启的参数,reload一次就可以生效,命令如下所示:

        mydb=# SELECT pg_reload_conf();
        pg_reload_conf
        ----------------
        t
        (1 row)

也可以使用pg_ctl命令reload配置,命令如下所示:

        [root@pghost1~]# su - postgres
        [postgres@pghost1~]$ /opt/pgsql/bin/pg_ctl -D /pgdata/10/data reload

1.6.4 允许远程访问数据库

在默认情况下,PostgreSQL实例是不允许通过远程访问数据库的,如下所示:

        [postgres@pghost1~]$ netstat -nlt | grep 1921
        Active Internet connections (only servers)
        Proto Recv-Q Send-Q Local Address           Foreign Address          State
        tcp        0      0127.0.0.1:1921           0.0.0.0:*               LISTEN
        tcp        0      0 ::1:1921                 :::*                    LISTEN

从其他主机访问数据库端口,将会被拒绝,如下所示:

        [postgres@pghost2~]$ telnet pghost11921
        Trying pghost1...
        telnet: connect to address pghost1: Connection refused

通过以下配置方法,允许从远程访问数据库。

1.修改监听地址

PostgreSQL管理监听地址的配置项为postgresql.conf文件中的listen_addresses。默认安装只监听本地环回地址localhost的连接,不允许使用TCP/IP建立远程连接,启用远程连接需要修改postgresql.conf中的listen_addresses参数。用文本编辑器打开postgresql.conf配置文件,命令如下所示:

        [postgres@pghost1~]$ vim /pgdata/10/data/postgresql.conf

找到名称为listen_addresses的配置项,如下所示:

        #listen_addresses = 'localhost'   # what IP address(es) to listen on;
            # comma-separated list of addresses;
            # defaults to 'localhost'; use '*' for all
            # (change requires restart)

关于listen_addresses参数的4行注释,的含义如下:

❑ what IP address(es) to listen on—监听什么IP地址?也就是允许用哪些IP地址访问,可以是一个IP,也可以是多个IP地址。

❑ comma-separated list of addresses; —以逗号分隔地址列表。

❑ defaults to 'localhost'; use '*' for all—默认是“localhost”,使用“*”允许所有地址;大多数的高可用架构都使用VIP的方式访问数据库,所以我们一般设置为“*”。

❑ (change requires restart)—修改这个参数需要重新启动数据库。

去掉listen_addresses这一行开头的“#”号,并把它的值修改为“*”,即允许所有地址访问数据库,如下所示:

      listen_addresses = '*'

修改完成之后重启数据库使配置生效,如下所示:

        [root@pghost1~]$ service postgresql-10 restart

2.修改pg_hba.conf文件

修改监听地址之后,还需要修改pg_hba.conf文件,回答pg_hba.conf的问题:允许哪些主机可以通过什么连接方式和认证方式通过哪个数据库用户连接哪个数据库?假设我们允许所有主机通过TCP/IP建立的连接,同时匹配SSL和非SSL连接,通过md5口令认证,使用pguser用户,连接mydb数据库,那么我们只需要在pg_hba.conf文件中增加一行,如下所示:

        [postgres@pghost1~]$ echo "host mydb pguser 0.0.0.0/0 md5" >> /pgdata/10/data/pg_hba.
            conf

修改pg_hba.conf文件之后需要reload使它生效,如下所示:

        [postgres@pghost1~]$ /opt/pgsql/bin/pg_ctl -D /pgdata/10/data/ reload
        server signaled
        2017-10-18 10:16:00.405 CST [36171] LOG:  received SIGHUP, reloading configuration
            files

现在就可以通过远程访问数据库了。

通常Windows防火墙和Linux系统的selinux和iptables也会影响远程访问,在Linux中一般可以关闭selinux,添加iptables项允许远程访问数据库服务器或关闭iptables,这部分内容可以根据操作系统的文档管理配置。

1.7 本章小结

本章介绍了PostgreSQL的历史和特点,介绍了如何获得PostgreSQL的学习资料以及如何与技术社区进行沟通交流。还介绍了如何安装部署PostgreSQL数据库服务器,以及PostgreSQL的应用程序大致功能。了解了如何配置PostgreSQL服务器,如何创建、管理数据库实例,以及基础的数据库配置项。通过本章的学习,读者已经可以独立创建PostgreSQL的数据库环境,进行简单的配置,可以在一个数据库实例中创建用户以及数据库了。