当前位置: 首页 > news >正文

postgresql

作者本人也搭建了一个docker镜像加速器,需要的朋友随时联系作者,镜像加速嘎嘎快,快速解决docker镜像拉不下的问题,文章最后带有作者wx,先好好学习吧。

在这里插入图片描述

一:PostgreSQL数据库

在这里插入图片描述

1.1:PostgreSQL介绍和特性

PostgreSQL是当前功能最强大的开源的关系数据库系统,支持跨平台的多种操作系统,基于C语言开发。通常简称为PG或PGSQL。

PostgreSQL宣称是世界上最先进的开源数据库。PostgreSQL的狂热者认为它的性能缺Oracle不分上下,而且没有高成本的负担。

PostgreSQL拥有着悠久的历史,可以追溯到1985年的加州大学伯克利分校的项目POSTGRES,是1977+年的由数据库科学家Michael+Stonebraker领导的Ingres项目的衍生品,为了专注于数据库理论的研究,在+版本4.2时伯克利正式终止了POSTGRES项目。

1994年,来自中国香港的两名伯克利的研究生Andrew Yu和 JollyChen向 POSTGRES 中增加了现在SQL语言的解释器,将Postgres改名为Postgres95,并将其源代码发布到互联网上,成为一个开源的数据库+管理系统。

1996年,Postgres95名称已经不合时宜,被更改为PostgreSQL,表示它支持查询语言标准,同时版本号+也重新从6.0开始。自从版本6.0之后,出现了很多后续发行版本。

PostgreSQL是100%社区驱动的开源项自,由全球范围内千人以上的社区责献者共同维护。PostgreSQL提供了一个完整功能的瓶本,而不像MySQL那样提供多个不同的瓶本,如社区版、商业版及企业版。

PostgreSQL的开源协议采用自由的BSD,MTT类型,这种开源协议允许任何人在保留版权声明的情况下使用复制,修改或者分享代码。

可靠性是PostgreSQL最优先关注的特性。普遍认为PostgreSQL坚如磐石并且设计精密,能够支持事务处理和关键任务应用。PostgreSQL提供一流的文档服务,包括全面的免费在线手册,以及旧版本手册的存档。社区的支持非常出色并且有独立厂商提供商业支持。

数据一致性和完整性也是PostgeSQL的高度优先事项。PostgreSQL是完全符合ACID原则(原子性、一致性、隔离性,持久性)的数据库:PostgreSQL对数据库访问提供强大的安全控制,不仅能够利用企业安全工具:如Kerberos和OpenSSL等,还可以根据自己的业务规则自定义核对方法,以确保数据的质量。数据库管理员最喜欢的功能是时间点恢复(point-in-time+recovery+简称PITR)期能,它具有灵活性,高可用性特征,能够打造快速故障的热备份服务器,以及快照和恢复到特定时间点等。但这还不是全部.该项目提供了很多方法来管理PostgreSQL,使PostgreSQL具有高可用性、负载均衡和同步功能,因此可以利用这些功能来满足特定需求

二:PostgreSQL安装

安装方法分为两种:

  • 二进制包进行安装

    各个linux的发行版本中,很多都内置了PostgreSQL的二进制安装包,但内置的版本可能较旧。对于二进制包安装的方法是通过不同发行版的linux下的包管理器进行的,如在RHEL系统相关版本下用yum命令,在Debian或Ubuntu下使用apt命令

  • 源码编译安装

    使用源码编译安装相对更灵活,用户可以有更多的选择,可以选择较新的版本。

2.1:ubuntu编译安装PostgreSQL

2.1.1:系统初始化和优化配置

在这里插入图片描述

2.2.2:安装依赖包

#Ubuntu
apt install -y gcc make libreadline-dev zlib1g-dev

2.2.3:源码编译安装

# 下载解压缩
wget https://ftp.postgresql.org/pub/source/v14.2/postgresql-14.2.tar.gz
tar -xvf postgresql-14.2.tar.gz
cd postgresql-14.2

#查看安装说明
root@gf:~/postgresql-14.2# vim INSTALL 
    ./configure
    make
    su
    make install
    adduser postgres
    mkdir /usr/local/pgsql/data
    chown postgres /usr/local/pgsql/data
    su - postgres
    /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
    /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start
    /usr/local/pgsql/bin/createdb test
    /usr/local/pgsql/bin/psql test
#开始编译
root@gf:~/postgresql-14.2# ./configure --prefix=/apps/pgsql
#查看编译选项
root@gf:~/postgresql-14.2# pg_config --configure 
make -j 2 world #默认 make不包括文档和其他模块,2表示主机的CPU核心数
make install-world #默认 make install 不包括安装文档

2.2.4:创建数据库用户和组

PostgreSQL默认不支持以root身份启动服务,虽然也可修改源码实现root启动,但基于安全考虑不建议,因此必须创建一个用于启动的PostgreSQL的普通用户

root@gf:~/postgresql-14.2# useradd -s /bin/bash -m -d /home/postgres postgres
root@gf:~/postgresql-14.2# echo -e "123456\n123456" |passwd postgres
root@gf:~/postgresql-14.2# echo postgres:123456 |chpasswd

2.2.5:创建数据目录并授权

mkdir -pv /pgsql/data
chown postgres.postgres /pgsql/data/

2.2.6:设置环境变量

root@gf:~/postgresql-14.2# cat /etc/profile.d/pgsql.sh 
export PGHOME=/apps/pgsql
export PATH=$PGHOME/bin/:$PATH
export PGDATA=/pgsql/data
export PGUSER=postgres
export MANPATH=/apps/pgsql/share/man:$MANPATH
root@gf:~/postgresql-14.2# chmod +x /etc/profile.d/pgsql.sh
root@gf:~/postgresql-14.2#. /etc/profile.d/pgsql.sh

2.2.7:初始化数据库

su - postgres
#初始化
initdb 
initdb -D $PGDATA
#如果没有指定选项 -D <datadir>,按环境变量$PGDATA指定的路径进行初始化

#生产建议初始化方式
initdb -A md5 $PGDATA -E utf8 --locale=C -U postgres -W
-A #指定local connections默认的身份验证方法
-D #指定数据目录
-E #指定字符集
--locale=C #指定语言环境
-U #指定数据库superuser用户名
-W #指定数据库superuser的用户密码

2.2.8:启动和关闭服务

#启动
pg_ctl -D /pgsql/data -l logfile start
postgres -D /pgsql/data &

#停止数据库的命令如下:
pg_ctl stop -D $PGDATA [-m SHUTDOWN-MODE]
其中-m是指定数据库的停止方法,有以下三种。
smart:等所有的连接中止后,关闭数据库。如果客户端连接不终止,则无法关闭数据库
fast: 快速关闭数据库,断开客户端的连接,让已有的事务回滚,然后正常关闭数据库。相当于Oracle数据关闭时的immediate模式,此为默认值,建议使用
immediate:立即关闭数据库,相当于数据库进程立即停止,直接退出,下次启动数据库需要进行恢复。相当于Oracle数据库关闭时的abort模式。

#smart关闭
pg_ctl stop -D /pgsql/data -ms
#fast关闭,推荐使用,也有默认模式
pg_ctl stop -D /pgsql/data -mf
#immediate相当于kill -9
pg_ctl stop -D /pgsql/data -mi

#或者发送信号,直接向数据库主进程发送的signal信号有以下三种。
SIGTERM: 发送此信号为Smart Shutdown关机模式
SIGINT: 发送此信号为Fast Shutdown关机模式
SIGQUIT: 发送此信号为Immediate Shutdown关机模式。

#重启
pg_ctl restart -mf

#源码目录中内置PostgreSQL的启动脚本
/root/postgresql-14.2/contrib/start-scripts/linux

范例:Ubuntu启动脚本实现开机自启PostgeSQL

cp /root/postgresql-14.2/contrib/start-scripts/linux /etc/init.d/postgresql
# 注意/etc/init.d/postgresql会和systemctl 的service冲突,需要把/etc/init.d/postgresql 移动到别的目录
root@gf:~# cat /etc/rc.local 
#!/bin/bash
su - postgres -c "/apps/pgsql/bin/pg_ctl -l logfile start"
#/etc/init.d/postgresql start

范例:ubuntu使用systemctl启动postgresql

root@gf:~# cat /lib/systemd/system/postgresql.service 
[Unit]
Description=PostgreSQL database server
After=network.target

[Service]
User=postgres
Group=postgres
ExecStart=/apps/pgsql/bin/postmaster -D /pgsql/data
ExecReload=/bin/kill -HUP

[Install]
WantedBy=multi-user.target
postgresql 一个进程带了许多子进程,一个人连接开一个进程
mysql 一个进程带了许多线程

2.2.9:查看编译的相关信息

postgres@gf:~$ pg_config 
BINDIR = /apps/pgsql/bin
DOCDIR = /apps/pgsql/share/doc
HTMLDIR = /apps/pgsql/share/doc
INCLUDEDIR = /apps/pgsql/include
PKGINCLUDEDIR = /apps/pgsql/include
INCLUDEDIR-SERVER = /apps/pgsql/include/server
LIBDIR = /apps/pgsql/lib
PKGLIBDIR = /apps/pgsql/lib
LOCALEDIR = /apps/pgsql/share/locale
MANDIR = /apps/pgsql/share/man
SHAREDIR = /apps/pgsql/share
SYSCONFDIR = /apps/pgsql/etc
PGXS = /apps/pgsql/lib/pgxs/src/makefiles/pgxs.mk
CONFIGURE =  '--prefix=/apps/pgsql'
CC = gcc
CPPFLAGS = -D_GNU_SOURCE
CFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -O2
CFLAGS_SL = -fPIC
LDFLAGS = -Wl,--as-needed -Wl,-rpath,'/apps/pgsql/lib',--enable-new-dtags
LDFLAGS_EX = 
LDFLAGS_SL = 
LIBS = -lpgcommon -lpgport -lz -lreadline -lpthread -lrt -ldl -lm 
VERSION = PostgreSQL 14.2

2.2:pg_ctl 命令管理PostgreSQL

pg_ctl 是一个实用的命令行工具,有以下功能

  • 初始化PostgreSQL数据库实例
  • 启动、终止、或重启PostgreSQL数据库服务
  • 查看PostgreSQL数据库服务的状态
  • 让数据库实例重新读取配置文件。允许给一个指定的PostgreSQL进程发信号
  • 控制standby服务器为可读写
  • 在windows平台下允许为数据库实例注册或取消一个系统服务

pg_ctl 命令格式

postgres@gf:~$ pg_ctl --help
pg_ctl is a utility to initialize, start, stop, or control a PostgreSQL server.

Usage:
  pg_ctl init[db]   [-D DATADIR] [-s] [-o OPTIONS]
  pg_ctl start      [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]
                    [-o OPTIONS] [-p PATH] [-c]
  pg_ctl stop       [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]
  pg_ctl restart    [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]
                    [-o OPTIONS] [-c]
  pg_ctl reload     [-D DATADIR] [-s]
  pg_ctl status     [-D DATADIR]
  pg_ctl promote    [-D DATADIR] [-W] [-t SECS] [-s]
  pg_ctl logrotate  [-D DATADIR] [-s]
  pg_ctl kill       SIGNALNAME PID

2.2.1:初始化实例

初始化PostgreSQL数据库实例的命令如下

#先切换用户
su - postgres

#初始化数据库
initdb [DATADIR]
pg_ctl init[db]   [-D DATADIR] [-s] [-o OPTIONS] 

#生产建议初始化方式
initdb -A md5 $PGDATA -E utf8 --locale=C -U postgres -W

#pg_ctl命令调用initdb命令创建一个新的PostgreSQL数据库实例,参数说明如下:
-s #只打印错误和警告信息,不打印提示性信息
-D DATADIR #指定数据库实例的数据库目录。如果没有指定DATADIR,使用环境变量PGDATA指定的路径
-o options #为直接传递给initdb命令的参数

范例:创建新的数据库实例数据

root@gf:~# mkdir /pgsql/data2
root@gf:~# chown postgres. /pgsql/data2/

root@gf:~# su - postgres
postgres@gf:~$ pg_ctl init -D /pgsql/data2
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.

fixing permissions on existing directory /pgsql/data2 ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: 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:

    /apps/pgsql/bin/pg_ctl -D /pgsql/data2 -l logfile start

postgres@gf:~$ ls /pgsql/data2/
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf

2.2.2:服务管理

2.2.2.1:查看服务状态

查询数据库实例状态的命令如下:

postgres@gf:/pgsql/data2$ pg_ctl status -D /pgsql/data
pg_ctl: server is running (PID: 4249)
/apps/pgsql/bin/postgres "-D" "/pgsql/data"
2.3.2.2:启动服务

启动PostgreSQL服务的命令:

pg_ctl start   [-w]  [-t SECS] [-s]  [-D DATADIR] [-l FILENAME] [-o options] -p [path] [-c]  

#参数说明如下
start #启动数据库实例
-w #等待启动完成
-t #等待启动完成的等待秒数,默认为60秒
-s #只打印错误和警告信息,不打印提示性信息
-D datadir #指定数据库实例的数据目录
-l #服务器日志输出附加在"filename" 文件上,如果该文件不存在则创建它
-o options #声明要直接传递给postgres的选项,具体可见postgres命令的帮助
-p path #指定postgres可执行文件的位置。默认情况下postgres可执行文件来自和pg_ctl相同的目录,不必使用该选项,除非要进行一些不同寻常的操作,或者产生了postgres执行文件找不到的错误
-c #提高服务器的软限制(ulimit -c),尝试允许数据库实例在有异常时产生一个coredump文件,以便于问题定位和故障分析

范例:

postgres@gf:/pgsql/data2$ pg_ctl status -D /pgsql/data
pg_ctl: server is running (PID: 4249)
/apps/pgsql/bin/postgres "-D" "/pgsql/data"
postgres@gf:/pgsql/data2$ pg_ctl start -D /pgsql/data2

2.3.2.3:停止服务

停止PostgreSQL数据库的命令如下:

pg_ctl stop [-D datadir] [-m s[mart] | f[ast] | i[mmediate]] [-W] [-t seconds] [-s]
#参数说明如下
-w #不等待数据库停下来,命令就返回
-m #指定停止的模式。前面已叙述过停止的几种模式了
#其他未说明的参数,其含义与启动数据库命令的参数相同。

范例:

postgres@gf:~$ pg_ctl stop -D /pgsql/data2
waiting for server to shut down....2025-01-14 03:24:53.802 UTC [4830] LOG:  received fast shutdown request
2025-01-14 03:24:53.802 UTC [4830] LOG:  aborting any active transactions
2025-01-14 03:24:53.803 UTC [4830] LOG:  background worker "logical replication launcher" (PID 4837) exited with exit code 1
2025-01-14 03:24:53.803 UTC [4832] LOG:  shutting down
2025-01-14 03:24:53.841 UTC [4830] LOG:  database system is shut down
 done
server stopped

postgres@gf:~$ pg_ctl status -D /pgsql/data2
pg_ctl: no server running

2.3.2.4:重启服务

重启PostgreSQL数据库的命令如下:

pg_ctl restart [-D datadir] [-m s[mart] | f[ast] | i[mmediate]] [-W] [-t seconds] [-s] [-o options] [-c]

#此命令的参数与启动和停止命令中参数含义相同
2.3.2.5:加载配置

在配置文件中改变参数后,需要使用上面这条命令使参数生效。

#修改配置文件 postgresql.conf 后,让修改生效的方法有两种

#方法一:在操作系统使用下面命令
pg_ctl reload [-D datadir] [-s]
#方法二:在psql中使用如下命令
postgres=# select pg_reload_conf();
#注意:加载配置操作只针对一些配置的修改生效,有些配置需要重新启动服务才生效

范例:

postgres@gf:~$ pg_ctl reload -D /pgsql/data
server signaled


#注意:修改端口不支持reload,只能restart
postgres@gf:~$ vim /pgsql/data/postgresql.conf
listen_addresses = '*'  

postgres@gf:~$ pg_ctl restart -D /pgsql/data
waiting for server to shut down.... done
server stopped
waiting for server to start....2025-01-14 03:41:41.029 UTC [4969] LOG:  starting PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit
2025-01-14 03:41:41.030 UTC [4969] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2025-01-14 03:41:41.030 UTC [4969] LOG:  listening on IPv6 address "::", port 5432
2025-01-14 03:41:41.043 UTC [4969] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2025-01-14 03:41:41.071 UTC [4970] LOG:  database system was shut down at 2025-01-14 03:41:40 UTC
2025-01-14 03:41:41.089 UTC [4969] LOG:  database system is ready to accept connections
 done
server started

2.3.3:pormote模式

在流复制架构中,在standby主机执行promote提升操作,恢复正常的读写操作

pg_ctl promote [-D datadir] [-W] [-t seconds] [-s]

备用服务器在指定数据目录中运行提升模式命令,结束备用模式并开始读写操作

3 PostgreSQL管理

3.1 配置文件介绍

PostgreSQL使用环境变量PGDATA指向的目录作为数据存放的目录。这个目录是在安装时指定的,所以在安装时需要指定一个合适的目录作为数据目录的根目录,而且,每一个PG数据库实例都需要有这样的一个目录。此数据目录的初始化是使用命令initdb来完成的。

初始化完成后,PGDATA数据目录下就会生成三个配置文件。

pg_hba.conf #认证配置文件,配置了允许哪些IP的主机访问数据库,认证的方法是什么等信息。
pg_ident.conf #认证方式ident的用户映射文件
postgresql.conf  #数据库实例的主配置文件,基本上所有的配置参数都在此文件中

3.2 数据库相关概念

3.2.1 数据库的结构组织

在这里插入图片描述

在一个PostgreSQL数据库系统中,数据的组织结构可以分为一下五层:

  • 实例:一个PostgreSQL对应一个安装的数据目录$PGDATA,即一个instance实例

  • 数据库:一个PostgreSQL数据库服务下可以管理多个数据库,当应用连接到一个数据库时,一般只能访问这个数据库中的数据,而不能访问其他数据库中的内容

    默认情况下初始实例只有三个数据库:postgres、template0、template1

  • 模式:一个数据库可以创建多个不同的名称空间即Schema,用于分隔不同的业务数据

  • 表和索引:一个数据库可以有多个表和索引。在PostgreSQL中表的术语称为Relation,而在其他数据库中通常叫Table

  • 行和列:每张表中有很多列和行数据,在PostgreSQL中行的术语一般为"Tuple",而在其他数据库中则叫"Row"

3.2.2 PostgreSQL中的术语

PostgreSQL有一些术语与其他数据库中不一样,了解了这些术语的意思,就能更好地看懂PostgreSQL中的文档

与其他数据库不同的术语如下:

  • Relation:表示表table或索引index,具体表示的是Table还是Index需要看具体情况
  • Tuple:表示表中的行,在其他数据库中使用Row来表示
  • Segment:每个表和索引都单独对应一个文件,即为segment,如果文件大小超过1GB,会创建多个相同名称但后缀不同的文件
  • Page:表示在磁盘中的数据块。在文件中以块为单位存放数据,默认值为8KB,最大可以为32KB
  • Buffer:表示内存中的数据块

范例:编译时可以指定segment大小

root@gf:~/postgresql-14.2# ./configure --help |grep segment
  --with-segsize=SEGSIZE  set table segment size in GB [1]

3.2.3 模板数据库template0和template1

template1和template0是PostgreSQL的模板数据库。所谓模板数据库就是创建新database时,PostgreSQL会基于模板数据库制作一份副本,其中会包含所有的数据库设置和数据文件。

PostgreSQL安装好以后会默认附带两个模板数据库:默认模板库为template0和template1

默认模板库为template1,也可以指定template0

不要对template0模板数据库进行任何修改,因为这是原始的赶紧模板

如果其它模板数据库被搞坏了,基于这个数据库做一个副本就可以了。

如果希望定制自己的模板数据库,那么请基于template1进行修改,或者自己另外创建一个模板数据库再修改。

template1和template0的区别主要有两点:

1、template1可以连接,template0不可以连接。

2、使用template1模板库时不可指定新的encoding和locale,而template0可以。

注意:template0和template1都不能被删除

3.2.4 模式schema

模式schema是数据库中的一个概念,可以将其理解为一个命名空间。不同的模式下可以有相同名称的表、函数等对象且互相不冲突。提出模式的概念是为了便于管理,只要有权限,每个模式(schema)的对象可以互相调用。

在PostgreSQL中,一个数据库包含一个或多个模式,一个模式中又包含了表、函数及操作符等数据库对象。

在PostgreSQL中,不能同时访问不同数据库中的对象,当要访问另一个数据库中的表或其他对象时,需要重新连接到这个新的数据库,而模式没有此限制。一个用户在连接到一个数据库后,就可以同时访问这个数据库中多个模式的对象。

通常情况下,创建和访问表的时候都不用指定模式,实际上这时访问的时public模式。每当我们创建一个新的数据库时,PostgreSQL都会自动创建一个名为public的模式。当登录到该数据库时,如果有特殊的指定,都是以该模式public操作各种数据对象的。

我们需要使用模式有一下几个主要原因:

  • 允许多个用户在使用同一个数据库时彼此互不干扰。
  • 把数据库对象放在不同的模式下,然后组织成逻辑组,让他们更便于管理
  • 第三方的应用可以放在不同的模式中,这样就不会和其它对象的名字冲突了
#创建模式
create schema schema_name;

#删除模式
drop schema schema_name;

#查看模式
\dn

要访问指定模式中的对象,需要先指定一个包含模式名及表名的名字,模式和表之间用一个"点"分开,如下:

schema_name.table_name

3.3 psql工具介绍和基本用法

psql是PostgreSQL中一个命令行交互式客户端工具,类似MySQL的mysql和Oracle中的命令行工具sqlplus,它允许你交互地输入SQL或命令,然后把他们发出给PostgreSQL服务器,再显示SQL或命令地结果。而且,输入的内容还可以来自于一个文件。此外,它还提供了一些命令和多种类似shell的特性来实现书写脚本,从而实现对大量任务的自动化工作。

虽然也可以使用PostgreSQL中图形化的客户端工具(如pgadmin)来实现上述功能。但如果掌握了psql的使用方法,将会体会到它的方便之处。因为psql是一个字符界面的工具,没有图形化工具使用上的一些限制。psql与pgAdmin之间的关系类似与vi与某些图形化工具的关系。

psql的实例命令和补全的功能

  • 可以使用上下键把以前使用过的命令或SQL语句调出来
  • 连续按两个tab键表示把命令补全或给出提示输入

psql命令格式

psql -h <hostname or ip> -p<端口> [数据库名称] -U [用户名称]

-h #指定要连接的数据库主机名或IP地址,默认local socket登录(由配置项unix_socket_directories指定)
-p #指定连接的数据库端口
#最后两个参数要数据库名和用户名

#这些连接参数也可以用环境变量指定,比如:
export PGDATABASE=testdb
export PGHOST=172.16.10.20
export PGPORT=5432
export PGUSER=postgres

#然后运行psql即可,其效果与运行psql -h 172.16.10.20 -p 5432 testdb postgres相同
#可通过下面命令查看详细帮助: man psql

范例:psql 本地登录PGSQL

root@gf:~# psql -U postgres
Password for user postgres: 
psql (14.2)
Type "help" for help.

postgres=# 


root@gf:~# psql -U postgres template1 
Password for user postgres: 
psql (14.2)
Type "help" for help.

template1=# 

范例:psql命令中直接执行SQL

root@gf:~# psql -U postgres -d postgres -c "select current_time"
Password for user postgres: 
    current_time    
--------------------
 07:21:06.320263+00
(1 row)

范例:psql命令中执行文件的SQL

root@gf:~# psql -U postgres -d postgres -f test.sql


#方法2
\i <文件名> #执行存储再外部文件的sql语句和命令
postgres=# \i hellodb.sql

3.4 连接管理

3.4.1 访问控制配置文件介绍

在PostgreSQL中,带有一个网络防火墙的功能的文件pg_hba.conf,可以控制允许设置哪些IP的机器访问数据库服务器。

HBA的意思是host-based authentication,也就是基于主机的认证,即实现PostgreSQL防火墙功能

initdb初始化数据目录时,会生成一个默认的pg_hba.conf文件。

pg_hba.conf文件的格式由很多记录组成,每条记录占一行。

以#开头的行为注释及空白行会被忽略。

一条记录由若干个空格或由制表符分割的字段组成,如果字段用引号包围,那么它可以包含空白。

每条记录声明一种连接类型、一个客户端IP地址范围(如果和连接类型相关)、一个数据库名、一个用户名字,以及对匹配这些参数的连接所使用的认证方法。

第一条匹配连接类型、客户端地址、连接请求的数据库名和用户名的记录将用于执行认证。如果选择了一条记录而且认证失败,那么将不考虑后面的记录;如果没有匹配的记录,访问将被拒绝。即从上向下匹配,一旦匹配则不会再向下检查

每条记录可以时下面七种格式之一:

# local         DATABASE  USER  METHOD  [OPTIONS]
# host          DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
# hostssl       DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
# hostnossl     DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
# hostgssenc    DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
# hostnogssenc  DATABASE  USER  ADDRESS  METHOD  [OPTIONS]

pg_hba.conf文件为pg实例的防火墙配置文件。配置文件格式分为5部分:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
  • 第1个字段只能时下面的取值。
    • local:这条记录匹配通过UNIX域套接字的连接认证。没有这种类型的记录,就不允许有UNIX域套接字的连接。当psql后面不指定主机名或IP地址时,即用UNIX域套接字的方式连接数据库。
    • host:这条记录匹配通过TCP/IP进行的连接。包括SSl和非SSl的连接
    • hostssl:这条记录匹配使用TCP/IP的SSL连接。必须是使用SSL加密的连接,且要使用这个选项,编译服务器时必须打开SSL支持,启动服务器时必须打开SSL配置选项
    • hostnossl:这条记录与hostssl相反,它只匹配哪些再TCP/IP上不使用ssl的连接请求
  • 第2个字段用于设置一个数据库名称,如果设置为all,表示可以匹配任何数据库,注意:如果设置为replication时比较特殊,表示允许流复制连接,而不是允许连接到一个名为"replication"的数据库上
  • 第3个字段用于设置一个用户的名称,如果设置为all,表示可以匹配任何用户
  • 第4个字段<ip/masklen>表示允许哪些IP地址来访问此服务器,如192.168.1.10/32表示只允许192.168.1.10这台主机访问数据库,192.168.1.0/24表示IP地址前缀为192.168.1.X的主机都允许访问数据库服务器
  • 第5个字段表示验证方法,PostgreSQL支持的认证配置方式很多,最常用的认证方法是trust、reject、md5和ident方法
#METHOD有如下值可选
md5: 执行SCRAM-SHA-256或MD5身份验证加密密码来验证,是推荐使用安全验证的方法
peer:从操作系统获取客户端的操作系统用户名,并检查它是否与请求的数据库用户名匹配。这仅适用于本地socket连接。
trust:允许无条件连接,允许任何PostgreSQL用户身份登录,而无需密码或任何其它身份验证
reject:拒绝任何条件连接,这对于从组中"过滤掉"某些主机非常有用
scram-sha-256:执行SCRAM-SHA-256身份验证以验证用户的密码
password:要提供未加密的密码以进行身份验证。由于密码是通过网络以明文形式发送的,因此不建议使用
gss:使用GSSAPI对用户进行身份验证,这仅使用于TCP/IP连接
sspi:使用SSPI对用户进行身份验证,这仅适用于Windows
ident:允许客户端上的特定操作系统用户连接到数据库。这种认证方式的使用场景是,客户端是主机上的某个操作系统用户,已经通过了操作系统的身份认证,是数据库服务器可以信任的用户,不需要在数据库层面再次监测身份。比如:如果配置了这种认证方式(配置中允许的用户名是dba)、这时操作系统用户dba下,就能以数据库用户dba的身份连接到数据库。服务器为了确定接收到的连接请求是客户端机器上的dba下,就能以数据库用户dba的身份连接到数据库。服务器为了确定接收到的连接请求确实是客户端机器上的dba用户发起的,而不是这台机器上其他用户发起的假冒请求,会向客户端机器上的ident服务发起请求,让ident服务查看此TCP连接是否是dba用户发起的,如果不是,说明是假冒,则认证失败。如果客户端通过本地连接到服务器,因为客户端与服务器在一台机器上,数据库服务器可以直接俄检查客户端的操作系统用户身份,就不需要向ident服务发送请求进行判断了。
ldap:使用LDAP服务器进行身份验证
radius:使用RADIUS服务器进行身份验证
cert:使用SSL客户端证书进行身份验证
pam:使用操作系统提供的可插入身份验证模块(PAM)服务进行身份验证。
bsd:使用操作系统提供的BSD身份验证服务进行身份验证。

范例:

#如果一台机器只给数据库使用,而没有其它用途,则可以在pg_hba.conf中加上下面一行配置:
local all all trust
#该配置表示在这台机器上,任何操作系统的用户都可以使用任何数据库用户(包括数据库超级用户)连接到数据库而不需要任何密码。因为这台主机只提供数据库使用,可以把不用的操作系统用户都禁止掉,以保证安全性

#如果数据库中有一个用户"dba",操作系统中也有一个用户"dba"
#在操作系统"dba"用户下连接数据库不需要密码验证的设置方法
local all dba ident

#如果想在数据库主机上使用密码验证,可以使用下面的配置项
local all all md5

#如果想让其它主机的连接都使用md5密码验证,则使用如下配置:
host all all 0.0.0.0/0 md5

#允许用户通过172.16.10.0/24的远程主机进行md5验证登录
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             172.16.10.0/24          md5

#允许用户wang通过任意远程主机进行md5验证的路test数据库
###################postgres=# CREATE USER gf WITH PASSWORD '123456'; #创建用户
host test wang 0.0.0.0/0 md5

3.4.2 打开远程连接

默认安装完的PG之监听local,如果要远程连接,需要监听对外提供服务的IP地址。

#修改用户postgres密码
####alter user postgres with password '1234565';

#查看监听端口,默认为127.0.0.1:5432
root@gf:~# vim /pgsql/data/postgresql.conf
listen_addresses = '*'
port = 5432    

#重启服务生效

postgres@gf:~$pg_ctl restart -mf

在这里插入图片描述

3.5 常用操作

3.5.1 查看psql帮助

#列出psql帮助用法
help
#列出以\开头的命令,即psql命令
\?

#列出所有SQL命令的帮助,注意:SQL语句必须以 ; 结束
\h

#查看指定SQL的帮助
\h create database
\help create user

3.5.2 设置显示信息的格式

#后续查看将竖着显示,类似于MySQL中的\G
\x
#开启命令执行时长提示
\timing on
#显示详细的信息,可以打印出报告问题的源代码位置
\set VERBOSITY verbose

范例:

postgres=# \x
Expanded display is on.

postgres=# \l
List of databases
-[ RECORD 1 ]-----+----------------------
Name              | postgres
Owner             | postgres
Encoding          | UTF8
Collate           | C
Ctype             | C
Access privileges | 
-[ RECORD 2 ]-----+----------------------
Name              | template0
Owner             | postgres
Encoding          | UTF8
Collate           | C
Ctype             | C
Access privileges | =c/postgres          +
                  | postgres=CTc/postgres
-[ RECORD 3 ]-----+----------------------
Name              | template1
Owner             | postgres
Encoding          | UTF8
Collate           | C
Ctype             | C
Access privileges | =c/postgres          +
                  | postgres=CTc/postgres

postgres=# select pg_sleep(3);
 pg_sleep 
----------
 
(1 row)

范例:

postgres=# \timing on
Timing is on.
postgres=# select pg_sleep(3);
 pg_sleep 
----------
 
(1 row)

Time: 3003.582 ms (00:03.004)


postgres=# \timing off
Timing is off.
postgres=# select pg_sleep(3);
 pg_sleep 
----------
 
(1 row)

范例:查看出错对应的源代码位置

postgres=# \set VERBOSITY verbose
postgres=# select wang;
2025-01-16 07:17:51.650 UTC [3507] ERROR:  column "wang" does not exist at character 8
2025-01-16 07:17:51.650 UTC [3507] STATEMENT:  select wang;
ERROR:  42703: column "wang" does not exist
LINE 1: select wang;
               ^
LOCATION:  errorMissingColumn, parse_relation.c:3599

3.5.3 数据库的创建和删除

创建数据库可以使用SQL语句create database实现,也可以利用createdb命令创建数据库

createdb是一个SQL命令CREATE DATABASE的封装

createdb命令语法格式如下:

createdb creates a PostgreSQL database.

Usage:
  createdb [OPTION]... [DBNAME] [DESCRIPTION]

Options:
  -D, --tablespace=TABLESPACE  tablespace指定数据库默认表空间
  -e, --echo                   将createdb生成的命令发送到服务端
  -E, --encoding=ENCODING      encoding指定数据库的编码
  -l, --locale=LOCALE          local指定数据库的语言环境
  -T, --template=TEMPLATE      template指定创建此数据库的模板

Connection options:
  -h, --host=HOSTNAME          host指定服务器的主机名
  -p, --port=PORT              port指定服务器监听的端口,或者socket文件
  -U, --username=USERNAME      username连接数据库的用户名
  -w, --no-password            忽略输入密码
  -W, --password               连接时强制要求输入密码
  
  dbname: 要创建的数据库名
  description:关于新创建的数据库相关的说明。

删除数据库可以使用SQL语句drop database实现

范例:创建数据库

#方法1
root@gf:~# createdb -h 172.16.10.20 -p 5432 -U postgres testdb
方法2
root@gf:~# psql
postgres=# create database testdb2;
CREATE DATABASE

范例:删除数据库

root@gf:~# psql
postgres=# drop database testdb2;
DROP DATABASE

范例:查看数据库存放目录的路径

postgres=# select oid,datname from pg_database;
  oid  |  datname  
-------+-----------
 12974 | postgres
 16385 | gf
     1 | template1
 12973 | template0
 16386 | testdb
(5 rows)


root@gf:~# ls /pgsql/data/base/
1  12973  12974  16385  16386

3.5.4 管理和查看模式

一个数据库包含一个或多个已命名的模式,模式又包含表。模式还可以包含其它对象,包括数据类型、函数、操作符等等。同一个对象名可以在不同的模式里使用而不会导致冲突;比如,schema1和schema2都可以包含一个名为test的表

#创建模式
postgres=# create schema schema_test;
CREATE SCHEMA

#删除模式
postgres=# drop schema schema_test;
DROP SCHEMA



#列出所有schema
postgres=# \dn
    List of schemas
    Name     |  Owner   
-------------+----------
 public      | postgres
 schema_test | postgres
(2 rows)


postgres=# create table t1(id int);
CREATE TABLE
postgres=# create table schema_test.t1(id int);
CREATE TABLE


postgres=# \dt
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | t1   | table | postgres
(1 row)


postgres=# \dt schema_test.t1
           List of relations
   Schema    | Name | Type  |  Owner   
-------------+------+-------+----------
 schema_test | t1   | table | postgres
(1 row)

3.5.5 查看和连接数据库

#列出所有的数据库名
postgres=# \l 
                             List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   
-----------+----------+----------+---------+-------+-----------------------
 gf        | postgres | UTF8     | C       | C     | 
 postgres  | postgres | UTF8     | C       | C     | 
 template0 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 testdb    | postgres | UTF8     | C       | C     | 
(5 rows)

#显示数据库详细信息,比如大小
postgres=# \l+
                                                               List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   |  Size   | Tablespace |                Description                 
-----------+----------+----------+---------+-------+-----------------------+---------+------------+--------------------------------------------
 gf        | postgres | UTF8     | C       | C     |                       | 8233 kB | pg_default | 
 postgres  | postgres | UTF8     | C       | C     |                       | 8241 kB | pg_default | default administrative connection database
 template0 | postgres | UTF8     | C       | C     | =c/postgres          +| 8081 kB | pg_default | unmodifiable empty database
           |          |          |         |       | postgres=CTc/postgres |         |            | 
 template1 | postgres | UTF8     | C       | C     | =c/postgres          +| 8233 kB | pg_default | default template for new databases
           |          |          |         |       | postgres=CTc/postgres |         |            | 
 testdb    | postgres | UTF8     | C       | C     |                       | 8233 kB | pg_default | 
(5 rows)

#查看当前连接信息
postgres=# \c
You are now connected to database "postgres" as user "postgres".

#查看当前连接详细信息
postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".

#连接数据库
postgres=# \c testdb
You are now connected to database "testdb" as user "postgres".
testdb=# 

3.5.6 管理表

PostgreSQL支持多种数据库类型实现表结构的创建

范例:查看支持数据类型

testdb=# select typname from pg_type;
                typname                 
----------------------------------------
 bool
 bytea
 char
 name
 int8
 int2
 int2vector
 int4
 regproc
 text
 oid
 tid
 xid
 cid
 oidvector
 pg_type
 pg_attribute
 pg_proc
 pg_class
 json
 xml

范例:管理表

testdb=# create table tb1 (id serial primary key,name text);
CREATE TABLE
testdb=# insert into tb1 (name) select (md5(random()::text)) from generate_series (2,10);
INSERT 0 9

testdb=# select * from tb1;
 id |               name               
----+----------------------------------
  1 | ec79605fbb560f02275bc4140b8c569e
  2 | c977bbc95db7ba5b4415ff0521cb9660
  3 | 24fde35babe0e80c4a9012a3187d09b1
  4 | 487c2aa8335d5f112c5cf418b0931a7d
  5 | b50bc0494fc2e7639de5675dfccfe205
  6 | c986f958b2a075ec7d6bac579e49c190
  7 | 02350c8102987e0dbd6eb964f2ca089f
  8 | e9042ae998d4052a03dacb44b606ab0d
  9 | 1e3f28ccfe917b480d0aa1e22bb81153
(9 rows)

#PostgreSQL中插入100万条记录只需要2s
testdb=# \timing on
Timing is on.

testdb=# insert into tb1 (name) select (md5(random()::text)) from generate_series (1,1000000);
INSERT 0 1000000
Time: 2513.017 ms (00:02.513)

#复制表结构,不复制数据

testdb=# create table tb2 (like tb1);
CREATE TABLE
Time: 11.038 ms

testdb=# \d tb2
                Table "public.tb2"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 name   | text    |           |          | 
 
 
testdb=# drop table tb2;
DROP TABLE
Time: 1.844 ms

3.5.7 查看表和表信息

#列出所有表,视图,序列
\d

#列出public的schema中所有的表名,相当于show tables;
\dt

#查看t1的表信息
\dt t1

#支持通配符*和?,以下显示所有t开头的表
\dt t*

#列出myschema模式的表结构
\dt schema_test.*

#查看t1的表结构,相当于desc
\d t1

#列出所有表信息,包括大小
testdb=# \dt+
                                   List of relations
 Schema | Name | Type  |  Owner   | Persistence | Access method |  Size  | Description 
--------+------+-------+----------+-------------+---------------+--------+-------------
 public | tb1  | table | postgres | permanent   | heap          | 236 MB | 
(1 row)



#列出表信息
testdb=# \dt tb1
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | tb1  | table | postgres
(1 row)


#列出表信息的大小信息
testdb=# \dt+ tb1
                                   List of relations
 Schema | Name | Type  |  Owner   | Persistence | Access method |  Size  | Description 
--------+------+-------+----------+-------------+---------------+--------+-------------
 public | tb1  | table | postgres | permanent   | heap          | 236 MB | 
(1 row)


#查看所有表
testdb=# select * from tb1;
   id    |               name               
---------+----------------------------------
       1 | ec79605fbb560f02275bc4140b8c569e
       2 | c977bbc95db7ba5b4415ff0521cb9660
       3 | 24fde35babe0e80c4a9012a3187d09b1
       4 | 487c2aa8335d5f112c5cf418b0931a7d
       5 | b50bc0494fc2e7639de5675dfccfe205
       6 | c986f958b2a075ec7d6bac579e49c190
       7 | 02350c8102987e0dbd6eb964f2ca089f
       8 | e9042ae998d4052a03dacb44b606ab0d
       9 | 1e3f28ccfe917b480d0aa1e22bb81153
 2623403 | 63ffddf2a501ac9478f7109ec876d13b
 2623404 | 83cfaae13505efc582b89344c3f1f3d4
 2623405 | 78fed3bf03ecbf6e14dd51d16426c875


#查看表大小
testdb=# select pg_total_relation_size('tb1');
 pg_total_relation_size 
------------------------
              328867840
(1 row)

testdb=# select pg_total_relation_size('tb1')/1024/1024||'MB';
 ?column? 
----------
 313MB
(1 row)

范例:查看表对应的文件路径

testdb=# select oid,datname from pg_database where datname='testdb';
  oid  | datname 
-------+---------
 16386 | testdb
(1 row)

testdb=# select relid from pg_stat_all_tables  where relname='tb1';
 relid 
-------
 16397
(1 row)

root@gf:~# ls /pgsql/data/base/16386/16397 -l
-rw------- 1 postgres postgres 247365632 Jan 20 13:55 /pgsql/data/base/16386/16397

范例:查看当前库中的所有表的统计信息

postgres=# select * from pg_stat_all_tables;
-[ RECORD 1 ]-------+------------------------
relid               | 2619
schemaname          | pg_catalog
relname             | pg_statistic
seq_scan            | 0
seq_tup_read        | 0
idx_scan            | 138
idx_tup_fetch       | 138
n_tup_ins           | 0
n_tup_upd           | 0
n_tup_del           | 0
n_tup_hot_upd       | 0
n_live_tup          | 0
n_dead_tup          | 0
n_mod_since_analyze | 0
n_ins_since_vacuum  | 0
last_vacuum         | 
last_autovacuum     | 
last_analyze        | 
last_autoanalyze    | 
vacuum_count        | 0
autovacuum_count    | 0
analyze_count       | 0
autoanalyze_count   | 0
-[ RECORD 2 ]-------+------------------------
relid               | 4155
schemaname          | pg_toast
relname             | pg_toast_3394
seq_scan            | 0



postgres=# \c testdb
You are now connected to database "testdb" as user "postgres".

#查看指定表t1的信息
testdb=# select * from pg_stat_all_tables where relname='tb1';
-[ RECORD 1 ]-------+------------------------------
relid               | 16397
schemaname          | public
relname             | tb1
seq_scan            | 4
seq_tup_read        | 2000027
idx_scan            | 0
idx_tup_fetch       | 0
n_tup_ins           | 3623402
n_tup_upd           | 0
n_tup_del           | 0
n_tup_hot_upd       | 0
n_live_tup          | 1000986
n_dead_tup          | 0
n_mod_since_analyze | 0
n_ins_since_vacuum  | 0
last_vacuum         | 
last_autovacuum     | 2025-01-20 05:44:50.028825+00
last_analyze        | 
last_autoanalyze    | 2025-01-20 05:44:50.865212+00
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 0
autoanalyze_count   | 1

3.5.8 系统表(system catalogs)

系统表的定义:

系统表也称为系统目录(system catalogs),是关系型数据库存放模式元数据的地方,比如表和列的信息,以及内部统计信息等。PostgreSQL的系统表也是普通表。虽然可以删除并重建这些表、增加列、插入和更新数值,但会导致系统损坏。通常情况下,不应该手工修改系统目录,通过相关SQL命令去实现。

例如:当执行CREATE DATABASE 时会向系统表pg_database中插入一行记录,并且实际上在磁盘上创建该数据库

系统表包括存放系统信息的普通表或者视图,系统视图建立在系统表之上。

系统表的创建

pg的每一个数据库中都有一套自己的系统表,其中大多数系统表都是在数据库创建时从模板数据库中拷贝过来的

系统表的维护

系统表中的信息由相的SQL命令关联至系统表自动维护

系统表的存储方式

和数据库相关的系统表在$PGDATA/base目录下相应数据库的文件夹下,文件夹命名为pg_database里记录的数据库oid(Object identifiers),系统表都有一个列名为对象表示符oid,用于标识postges里各个对象,如表、序列、索引等,以前版本是隐藏的

所有数据库共享的系统表,如pg_database,保存在$PGDATA/global下

范例:查看系统表

#查看系统表
testdb=# \dS
                         List of relations
   Schema   |              Name               |   Type   |  Owner   
------------+---------------------------------+----------+----------
 pg_catalog | pg_aggregate                    | table    | postgres
 pg_catalog | pg_am                           | table    | postgres
 pg_catalog | pg_amop                         | table    | postgres
 pg_catalog | pg_amproc                       | table    | postgres
 pg_catalog | pg_attrdef                      | table    | postgres
 pg_catalog | pg_attribute                    | table    | postgres
 pg_catalog | pg_auth_members                 | table    | postgres
 pg_catalog | pg_authid                       | table    | postgres
 pg_catalog | pg_available_extension_versions | view     | postgres
 pg_catalog | pg_available_extensions         | view     | postgres
 pg_catalog | pg_backend_memory_contexts      | view     | postgres



testdb=# \dS+
                                                      List of relations
   Schema   |              Name               |   Type   |  Owner   | Persistence | Access method |    Size    | Description 
------------+---------------------------------+----------+----------+-------------+---------------+------------+-------------
 pg_catalog | pg_aggregate                    | table    | postgres | permanent   | heap          | 56 kB      | 
 pg_catalog | pg_am                           | table    | postgres | permanent   | heap          | 40 kB      | 
 pg_catalog | pg_amop                         | table    | postgres | permanent   | heap          | 88 kB      | 
 pg_catalog | pg_amproc                       | table    | postgres | permanent   | heap          | 72 kB      | 
 pg_catalog | pg_attrdef                      | table    | postgres | permanent   | heap          | 16 kB      | 
 pg_catalog | pg_attribute                    | table    | postgres | permanent   | heap          | 480 kB     | 
 pg_catalog | pg_auth_members                 | table    | postgres | permanent   | heap          | 40 kB      | 
 pg_catalog | pg_authid                       | table    | postgres | permanent   | heap          | 48 kB      | 
 pg_catalog | pg_available_extension_versions | view     | postgres | permanent   |               | 0 bytes    | 



#列出所有pg开头的系统表
testdb=# \dt pg_*
                    List of relations
   Schema   |          Name           | Type  |  Owner   
------------+-------------------------+-------+----------
 pg_catalog | pg_aggregate            | table | postgres
 pg_catalog | pg_am                   | table | postgres
 pg_catalog | pg_amop                 | table | postgres
 pg_catalog | pg_amproc               | table | postgres
 pg_catalog | pg_attrdef              | table | postgres
 pg_catalog | pg_attribute            | table | postgres
 pg_catalog | pg_auth_members         | table | postgres
 pg_catalog | pg_authid               | table | postgres
 pg_catalog | pg_cast                 | table | postgres


#列出所有pg开头的系统视图
testdb=# \dv pg_*
                       List of relations
   Schema   |              Name               | Type |  Owner   
------------+---------------------------------+------+----------
 pg_catalog | pg_available_extension_versions | view | postgres
 pg_catalog | pg_available_extensions         | view | postgres
 pg_catalog | pg_backend_memory_contexts      | view | postgres
 pg_catalog | pg_config                       | view | postgres
 pg_catalog | pg_cursors                      | view | postgres
 pg_catalog | pg_file_settings                | view | postgres
 pg_catalog | pg_group                        | view | postgres
 pg_catalog | pg_hba_file_rules               | view | postgres


#查看系统表pg_database的结构
testdb=# \d pg_database
               Table "pg_catalog.pg_database"
    Column     |   Type    | Collation | Nullable | Default 
---------------+-----------+-----------+----------+---------
 oid           | oid       |           | not null | 
 datname       | name      |           | not null | 
 datdba        | oid       |           | not null | 
 encoding      | integer   |           | not null | 
 datcollate    | name      |           | not null | 
 datctype      | name      |           | not null | 
 datistemplate | boolean   |           | not null | 
 datallowconn  | boolean   |           | not null | 
 datconnlimit  | integer   |           | not null | 
 datlastsysoid | oid       |           | not null | 
 datfrozenxid  | xid       |           | not null | 
 datminmxid    | xid       |           | not null | 
 dattablespace | oid       |           | not null | 
 datacl        | aclitem[] |           |          | 
Indexes:
    "pg_database_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global"
    "pg_database_datname_index" UNIQUE CONSTRAINT, btree (datname), tablespace "pg_global"
Tablespace: "pg_global"

范例:查看指定表对应的文件

gf2=# select * from pg_relation_filepath('tb1');
 pg_relation_filepath 
----------------------
 base/16415/16416
(1 row)


root@gf:~# ll /pgsql/data/base/16415/16416 
-rw------- 1 postgres postgres 8192 Jan 21 13:44 /pgsql/data/base/16415/16416
root@gf:~# 

3.5.9 表的CRUD

SQL的CRUD,即Insert、update、delete、select四条语句范例:

gf2=# create table tb1 (id serial,name varchar(10));
CREATE TABLE
gf2=# \d tb1;
                                   Table "public.tb1"
 Column |         Type          | Collation | Nullable |             Default             
--------+-----------------------+-----------+----------+---------------------------------
 id     | integer               |           | not null | nextval('tb1_id_seq'::regclass)
 name   | character varying(10) |           |          | 

gf2=# insert into tb1 (name)values ('wang');
INSERT 0 1
gf2=# insert into tb1 (name)values ('li');
INSERT 0 1
gf2=# select * from tb1;
 id | name 
----+------
  1 | wang
  2 | li
(2 rows)

gf2=# update tb1 set name='gao' where id =2;
UPDATE 1
gf2=# select * from tb1;
 id | name 
----+------
  1 | wang
  2 | gao
(2 rows)


gf2=# delete from tb1 where id=2;
DELETE 1
gf2=# select * from tb1;
 id | name 
----+------
  1 | wang
(1 row)


#清空表
gf2=# truncate tb1;
TRUNCATE TABLE
gf2=# select * from tb1;
 id | name 
----+------
(0 rows)

范例:查看表的列信息及大小

hellodb=# \d student;
Did not find any relation named "student".
hellodb=# \d students;
                      Table "public.students"
  Column   |         Type          | Collation | Nullable | Default 
-----------+-----------------------+-----------+----------+---------
 stuid     | integer               |           | not null | 
 name      | character varying(50) |           | not null | 
 age       | smallint              |           | not null | 
 gender    | character(1)          |           | not null | 
 classid   | smallint              |           |          | 
 teacherid | integer               |           |          | 
Indexes:
    "students_pkey" PRIMARY KEY, btree (stuid)


hellodb=# select pg_column_size(name),name from students;
 pg_column_size |     name      
----------------+---------------
             12 | Shi Zhongyu
             11 | Shi Potian
             10 | Xie Yanke
             10 | Ding Dian
             10 | Yu Yutong
              9 | Shi Qing
              7 | Xi Ren
             10 | Lin Daiyu
             13 | Ren Yingying
             13 | Yue Lingshan
             14 | Yuan Chengzhi
             13 | Wen Qingqing
             13 | Tian Boguang
             12 | Lu Wushuang
              8 | Duan Yu
              7 | Xu Zhu
             10 | Lin Chong
              9 | Hua Rong
             12 | Xue Baochai
             10 | Diao Chan
             14 | Huang Yueying
             10 | Xiao Qiao
              8 | Ma Chao
              8 | Xu Xian
             12 | Sun Dasheng
(25 rows)

范例:

hellodb=# select generate_series(3,6);
 generate_series 
-----------------
               3
               4
               5
               6
(4 rows)

3.5.10 索引管理

范例:创建和删除索引

gf=# create table tb1(id int,info text,crt_time timestamp);
CREATE TABLE
gf=# insert into tb1 select generate_series(1,100000),md5(random()::text),clock_timestamp();
INSERT 0 100000

gf=# select * from tb1 limit 3;
 id |               info               |          crt_time          
----+----------------------------------+----------------------------
  1 | 1591c217a821b9e561ef1107a97fc5b0 | 2025-01-21 06:11:39.800075
  2 | c1728ca3f7764b23ce73b58d835f2eec | 2025-01-21 06:11:39.8002
  3 | 700dfd3d6d88ba76b878746064c25a67 | 2025-01-21 06:11:39.800204
(3 rows)


#创建索引
gf=# create index idx_tb1_id on tb1(id);
CREATE INDEX


gf=# \d tb1;
                           Table "public.tb1"
  Column  |            Type             | Collation | Nullable | Default 
----------+-----------------------------+-----------+----------+---------
 id       | integer                     |           |          | 
 info     | text                        |           |          | 
 crt_time | timestamp without time zone |           |          | 
Indexes:
    "idx_tb1_id" btree (id)


#删除索引
gf=# drop index idx_tb1_id;
DROP INDEX

gf=# \d tb1;
                           Table "public.tb1"
  Column  |            Type             | Collation | Nullable | Default 
----------+-----------------------------+-----------+----------+---------
 id       | integer                     |           |          | 
 info     | text                        |           |          | 
 crt_time | timestamp without time zone |           |          | 


范例:使用索引

#打开时间
gf=# \timing on
Timing is on.

#查询条件是索引列
gf=# explain analyze select * from tb1 where id =99999;
                                                   QUERY PLAN                                                    
-----------------------------------------------------------------------------------------------------------------
 Index Scan using idx_tb1_id on tb1  (cost=0.29..8.31 rows=1 width=45) (actual time=0.029..0.029 rows=1 loops=1)
   Index Cond: (id = 99999)
 Planning Time: 0.155 ms
 Execution Time: 0.064 ms
(4 rows)

Time: 0.908 ms

#查询条件不是索引列
gf=# explain analyze select * from tb1 where info ='700dfd3d6d88ba76b878746064c25a67';
                                           QUERY PLAN                                            
-------------------------------------------------------------------------------------------------
 Seq Scan on tb1  (cost=0.00..2185.00 rows=1 width=45) (actual time=0.007..5.094 rows=1 loops=1)
   Filter: (info = '700dfd3d6d88ba76b878746064c25a67'::text)
   Rows Removed by Filter: 99999
 Planning Time: 0.049 ms
 Execution Time: 5.103 ms
(5 rows)

Time: 5.481 ms


#关闭索引
gf=# set enable_indexscan=off;
SET
gf=# set enable_bitmapscan=off;
SET


gf=# explain analyze select * from tb1 where id =99999;
                                           QUERY PLAN                                            
-------------------------------------------------------------------------------------------------
 Seq Scan on tb1  (cost=0.00..2185.00 rows=1 width=45) (actual time=4.570..4.572 rows=1 loops=1)
   Filter: (id = 99999)
   Rows Removed by Filter: 99999
 Planning Time: 0.049 ms
 Execution Time: 4.583 ms
(5 rows)

Time: 4.906 ms


gf=# explain (analyze,verbose,costs,buffers,timing) select * from tb1 where id =99999;

3.5.11 表空间

#列出所有表空间,实际上PostgreSQL中的表空间就是对应一个目录,放在这个表空间的表,就是把表的数据文件放到这个表空间下。
gf=# \db
       List of tablespaces
    Name    |  Owner   | Location 
------------+----------+----------
 pg_default | postgres | 
 pg_global  | postgres | 
(2 rows)

#复制表到文件中
gf=# select * from tb1;
   id   |               info               |          crt_time          
--------+----------------------------------+----------------------------
      1 | 1591c217a821b9e561ef1107a97fc5b0 | 2025-01-21 06:11:39.800075
      2 | c1728ca3f7764b23ce73b58d835f2eec | 2025-01-21 06:11:39.8002
      3 | 700dfd3d6d88ba76b878746064c25a67 | 2025-01-21 06:11:39.800204
      4 | 6c51c0625e6e9be90de55123f41fd696 | 2025-01-21 06:11:39.800205


postgres=# copy tb1 to '/tmp/1.txt';


root@gf:~# cat /tmp/1.txt

范例:表空间pg_tblspc目录

gf2=# create tablespace ts1 location '/home/postgres/ts1/';
CREATE TABLESPACE

gf2-# \db
            List of tablespaces
    Name    |  Owner   |      Location      
------------+----------+--------------------
 pg_default | postgres | 
 pg_global  | postgres | 
 ts1        | postgres | /home/postgres/ts1
(3 rows)

root@gf:~# ls /home/postgres/ts1/PG_14_202107181/

root@gf:~# readlink /pgsql/data/pg_tblspc/16473
/home/postgres/ts1

范例:查看表空间对应的文件

gf=# create tablespace ts2 location '/home/postgres/ts2/';
CREATE TABLESPACE

gf=# create table tb2(id int) tablespace ts2;
CREATE TABLE

gf=# select * from pg_relation_filepath('tb2');
            pg_relation_filepath             
---------------------------------------------
 pg_tblspc/16475/PG_14_202107181/16385/16476
(1 row)

root@gf:~# tree /pgsql/data/pg_tblspc/
/pgsql/data/pg_tblspc/
├── 16473 -> /home/postgres/ts1
└── 16475 -> /home/postgres/ts2

1 directory, 1 file
root@gf:~# 

3.5.12 查看系统信息

可以通过系统函数查看系统信息,也可以通过show/set查看和修改配置

#查看版本信息
postgres=# select version();
                                               version                                               
-----------------------------------------------------------------------------------------------------
 PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit
(1 row)

#查看数据库启动时间
postgres=# select pg_postmaster_start_time();
   pg_postmaster_start_time    
-------------------------------
 2025-01-21 05:30:43.032863+00
(1 row


#查看加载配置文件时间
postgres=# select pg_conf_load_time();
       pg_conf_load_time       
-------------------------------
 2025-01-21 07:40:03.965309+00
(1 row)

#查看时区和时间
postgres=# show timezone;
 TimeZone 
----------
 Etc/UTC
(1 row)


#临时修改
postgres=# set timezone='Asia/Shanghai';
SET

#永久修改时区
postgres@gf:~$ vim /pgsql/data/postgresql.conf
timezone = 'Asia/Shanghai'


postgres=# select now();
              now              
-------------------------------
 2025-01-21 15:43:48.722282+08
(1 row)


postgres=# select user;
   user   
----------
 postgres
(1 row)


postgres=# select current_user;
 current_user 
--------------
 postgres
(1 row)


postgres=# select session_user;
 session_user 
--------------
 postgres
(1 row)


#查看当前数据库
postgres=# \c testdb
You are now connected to database "testdb" as user "postgres".

testdb=# select current_database();
 current_database 
------------------
 testdb
(1 row)


#查看当前session所在的客户端IP和端口
root@gf:~# psql -h 172.16.10.20 -U postgres
postgres=# select inet_client_addr(),inet_client_port();
 inet_client_addr | inet_client_port 
------------------+------------------
 172.16.10.20     |            37820
(1 row)

#查看当前session所连接的数据库服务器的IP和端口
postgres=# select inet_server_addr(),inet_server_port();
 inet_server_addr | inet_server_port 
------------------+------------------
 172.16.10.20     |             5432
(1 row)


#查询当前session对应的后台服务时程pid
postgres=# select pg_backend_pid();
 pg_backend_pid 
----------------
           4805
(1 row)

#查看当前内置变量
postgres=# \set


#查看当前指定配置
postgres=# show max_connections;
 max_connections 
-----------------
 100
(1 row)

postgres=# select current_setting('max_connections');
 current_setting 
-----------------
 100
(1 row)

postgres=# select current_setting('listen_addresses');
 current_setting 
-----------------
 *
(1 row)


#显示系统函数
postgres=# \dfS+

#查看连接数
postgres=# select count(*) from pg_stat_activity;
 count 
-------
     6
(1 row)


postgres=# select setting from pg_settings where name='max_connections';
 setting 
---------
 100
(1 row)

#查看所有设置名称
postgres=# select name from pg_settings;
                  name                  
----------------------------------------
 allow_system_table_mods
 application_name
 archive_cleanup_command
 archive_command
 archive_mode
 archive_timeout
 array_nulls
 authentication_timeout
 autovacuum
 autovacuum_analyze_scale_factor
 autovacuum_analyze_threshold
 autovacuum_freeze_max_age
 autovacuum_max_workers
 autovacuum_multixact_freeze_max_age



#查看当前设置名和值
postgres=# select name,setting from pg_settings;
                  name                  |            setting             
----------------------------------------+--------------------------------
 allow_system_table_mods                | off
 application_name                       | psql
 archive_cleanup_command                | 
 archive_command                        | (disabled)
 archive_mode                           | off
 archive_timeout                        | 0
 array_nulls                            | on
 authentication_timeout                 | 60
 autovacuum                             | on
 autovacuum_analyze_scale_factor        | 0.1
 autovacuum_analyze_threshold           | 50
 autovacuum_freeze_max_age              | 200000000
 autovacuum_max_workers                 | 3
 autovacuum_multixact_freeze_max_age    | 400000000
 autovacuum_naptime                     | 60

#查看指定的当前的参数设置
postgres=# show port;
 port 
------
 5432
(1 row)


#是否开启归档模式
postgres=# show archive_mode;
 archive_mode 
--------------
 off
(1 row)

范例:show和set查看和修改配置

#查看参数
SHOW name;
SHOW all;

postgres=# show all;
                  name                  |            setting             |                                                               descri
ption                                                               
----------------------------------------+--------------------------------+---------------------------------------------------------------------
--------------------------------------------------------------------
 allow_system_table_mods                | off                            | Allows modifications of the structure of system tables.
 application_name                       | psql                           | Sets the application name to be reported in statistics and logs.
 archive_cleanup_command                |                                | Sets the shell command that will be executed at every restart point.
 archive_command                        | (disabled)                     | Sets the shell command that will be called to archive a WAL file.
 archive_mode                           | off                            | Allows archiving of WAL files using archive_command.
 archive_timeout                        | 0                              | Forces a switch to the next WAL file if a new file has not been star
ted within N seconds.
 array_nulls                            | on                             | Enable input of NULL elements in arrays.
 authentication_timeout                 | 1min                           | Sets the maximum allowed time to complete client authentication.
 autovacuum                             | on                             | Starts the autovacuum subprocess.
 autovacuum_analyze_scale_factor        | 0.1                            | Number of tuple inserts, updates, or deletes prior to analyze as a f
raction of reltuples.

#修改配置
SET [ SESSION | LOCAL ] configuration_parameter { TO | = } { value | 'value' | DEFAULT }
SET [ SESSION | LOCAL ] TIME ZONE { timezone | LOCAL | DEFAULT }

# 设置执行维护任务(如索引创建和重组)时的工作内存大小
postgres=# show maintenance_work_mem;
 maintenance_work_mem 
----------------------
 64MB
(1 row)


postgres=# set maintenance_work_mem to '128MB';
SET
postgres=# show maintenance_work_mem;
 maintenance_work_mem 
----------------------
 128MB
(1 row)


#注意:不是所有配置都可以直接修改的
postgres=# set max_connections to '200';
ERROR:  parameter "max_connections" cannot be changed without restarting the server
postgres=# 


#查看数据库大小,pg_size_pretty函数会把数字以MB,GB等易读格式显示
hellodb=# select pg_database_size('hellodb'),pg_size_pretty(pg_database_size('hellodb'));
 pg_database_size | pg_size_pretty 
------------------+----------------
          8643363 | 8441 kB
(1 row)

范例:explain可以查看SQL的执行计划

hellodb=# explain select * from students;
                         QUERY PLAN                          
-------------------------------------------------------------
 Seq Scan on students  (cost=0.00..14.90 rows=490 width=138)
(1 row)


hellodb=# explain analyze select * from students;
                                               QUERY PLAN                                               
--------------------------------------------------------------------------------------------------------
 Seq Scan on students  (cost=0.00..14.90 rows=490 width=138) (actual time=0.038..0.040 rows=25 loops=1)
 Planning Time: 0.031 ms
 Execution Time: 0.048 ms
(3 rows)


hellodb=# explain analyze verbose select * from students;
                                                  QUERY PLAN                                                   
---------------------------------------------------------------------------------------------------------------
 Seq Scan on public.students  (cost=0.00..14.90 rows=490 width=138) (actual time=0.005..0.007 rows=25 loops=1)
   Output: stuid, name, age, gender, classid, teacherid
 Planning Time: 0.054 ms
 Execution Time: 0.014 ms
(4 rows)

3.5.13 查看用户和权限

#查看所有用户\du或\dg

hellodb=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 gf        |                                                            | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

#查看当前用户
postgres=# select user;
   user   
----------
 postgres
(1 row)


postgres=# select current_user;
 current_user 
--------------
 postgres
(1 row)

#显示表,视图,序列的权限分配情况
hellodb=# \z
                              Access privileges
 Schema |   Name   | Type  | Access privileges | Column privileges | Policies 
--------+----------+-------+-------------------+-------------------+----------
 public | classes  | table |                   |                   | 
 public | coc      | table |                   |                   | 
 public | courses  | table |                   |                   | 
 public | scores   | table |                   |                   | 
 public | students | table |                   |                   | 
 public | teachers | table |                   |                   | 
 public | toc      | table |                   |                   | 
(7 rows)

hellodb=# \z coc
                            Access privileges
 Schema | Name | Type  | Access privileges | Column privileges | Policies 
--------+------+-------+-------------------+-------------------+----------
 public | coc  | table |                   |                   | 
(1 row)


#和\z功能相同
hellodb=# \dp
                              Access privileges
 Schema |   Name   | Type  | Access privileges | Column privileges | Policies 
--------+----------+-------+-------------------+-------------------+----------
 public | classes  | table |                   |                   | 
 public | coc      | table |                   |                   | 
 public | courses  | table |                   |                   | 
 public | scores   | table |                   |                   | 
 public | students | table |                   |                   | 
 public | teachers | table |                   |                   | 
 public | toc      | table |                   |                   | 
(7 rows)

3.5.14 事务管理和锁

PGSQL的事务中支持DML,DDL(除了create database,create tablespace),DCL

DML(Data Manipulation Language)语句:数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性,常用的语句关键字主要包括 insert、delete、udpate 和select 等。(增添改查)

DDL(Data Definition Languages)语句:数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象的定义。常用的语句关键字主要包括 create、drop、alter等。

DCL(Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括 grant、revoke 等。
DDL 语句:

DDL 是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改的操作语言。它和 DML 语言的最大区别是 DML 只是对表内部数据的操作,而不涉及到表的定义、结构的修改,更不会涉及到其他对象。DDL 语句更多的被数据库管理员(DBA)所使用,一般的开发人员很少使用

在psql中事务是自动提交的。和MySQL相同,执行完一条delete或update语句后,事务就自动提交了

如果不想自动提交,方法有两种

方法一:运行begin;命令,然后执行DML,DDL,DCL等语句,最后再执行commit或rollback语句。

方法二:直接使用psql中的命令关闭自动提交的功能。\set AUTOCOMMIT off,注意,命令中AUTOCOMMIT是大写的,不能使用小写,如果使用小写、虽然不会报错,但会导致关闭自动提交的操作不起作用。

#开启事务
BEGIN [ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }]

#提交和取消事务
COMMIT | END
ROLLBACK

#关闭自动提交,可以用rollback取消DML语句
\set AUTOCOMMIT OFF
\SET AUTOCOMMIT ON

#查看AUTOCOMMIT状态
\echo :AUTOCOMMIT

#查看事务ID
select txid_current();

范例:

gf=# begin;
BEGIN
gf=*# create table tb3(id int);
CREATE TABLE
gf=*# insert into tb3 values(1);
INSERT 0 1
gf=*# select * from tb3;
 id 
----
  1
(1 row)

gf=*# rollback;
ROLLBACK


gf=# \d
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | tb1  | table | postgres
 public | tb2  | table | postgres
(2 rows)


gf=# select txid_current();
 txid_current 
--------------
          792
(1 row)


#事务块中不支持create database
gf=# begin;
BEGIN
gf=*# create database gf3;
ERROR:  CREATE DATABASE cannot run inside a transaction block

#查看ctid(数据所在的数据块的编号及位移),xmin(插入事务XID),xmax(删除记录的事务XID)
gf=# select ctid,xmin,xmax,* from tb1;
   ctid    | xmin | xmax |   id   |               info               |          crt_time          
-----------+------+------+--------+----------------------------------+----------------------------
 (0,1)     |  780 |    0 |      1 | 1591c217a821b9e561ef1107a97fc5b0 | 2025-01-21 06:11:39.800075
 (0,2)     |  780 |    0 |      2 | c1728ca3f7764b23ce73b58d835f2eec | 2025-01-21 06:11:39.8002
 (0,3)     |  780 |    0 |      3 | 700dfd3d6d88ba76b878746064c25a67 | 2025-01-21 06:11:39.800204
 (0,4)     |  780 |    0 |      4 | 6c51c0625e6e9be90de55123f41fd696 | 2025-01-21 06:11:39.800205


#查看锁信息
gf=# select relation::regclass,* from pg_locks;
 relation |  locktype  | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsub
id | virtualtransaction | pid  |      mode       | granted | fastpath | waitstart 
----------+------------+----------+----------+------+-------+------------+---------------+---------+-------+-------
---+--------------------+------+-----------------+---------+----------+-----------
 pg_locks | relation   |    16385 |    12290 |      |       |            |               |         |       |       
   | 4/64               | 3594 | AccessShareLock | t       | t        | 
          | virtualxid |          |          |      |       | 4/64       |               |         |       |       
   | 4/64               | 3594 | ExclusiveLock   | t       | t        | 
(2 rows)

3.5.15 常用的系统函数

常用系统函数

#查看当前日志文件lsn位置;
select pg_current_wal_lsn();

#当前xlog buffer中的insert位置
select pg_current_wal_insert_lsn();

#查看某个lsn对应的日志名
select pg_walfile_name(lsn);

#查看某个lsn在日志中的偏移量:
select pg_walfile_name_offset('0/2AF98508');

#查看两个lsn位置的差距
select pg_wal_lsn_diff('lsn1','lsn2')

#查看备库接收到的lsn位置
select pg_last_wal_receive_lsn();

#查看备库回放的lsn位置
select pg_last_xact_replay_timestamp();

#创建还原点
select pg_create_restore_point(now()::text);

#查看表的数据文件路径,filenode:
select pg_relation_filenode('表名');

#查看表students的oid
select 'students'::regclass::oid;

#查看当前会话pid;
select pg_backend_pid();

#生成序列
select generate_series(1,8,2);

#生成uuid(pg13新特性)
select gen_random_uuid();

#重载配置文件信息
select pg_reload_conf();

#查看数据库启动时间:
select pg_postmaster_start_time();

3.6 用户和角色

PostgreSQL使用角色role的概念来管理数据库访问权限。角色是一系列相关权限的集合。为了管理方便,通常会把一系列相关的数据库赋给一个角色,如果那个用户需要这些权限,就把角色赋给相应的用户。由于用户也拥有一系列的相关权限,未来简化管理,在PostgreSQL中,角色与用户是没有区别的,一个用户也是一个角色,因此可以把一个用户的权限赋给另一个用户。

用户和角色在整个数据库实例中都是全局的,即在同一个实例中的不同数据库中,看到的用户也都是相同的。

在初始化数据库实例时,会创建一个预定义的超级用户,这个用户的名称与初始化该数据库实例的操作系统用户名相同。比如:如果数据库实例是建立在操作系统用户dba(通常使用postgres用户)下的,这个数据库超级用户的名称也会叫dba。可以用这个超级用户连接数据库,注意:dba默认会连接同名的数据库dba,而默认dba不存在,所以需要登录时指定连接数据库postgres进行登录,然后在创建其它的用户

3.6.1 创建用户和角色

在PostgreSQL中,用户与角色是没有区别的。

用户和角色可以用来实现以下功能:

  • 用来登录数据库实例
  • 管理数据库对象

创建用户与角色的语法如下:

CREATE USER name [ [ WITH ] option [ ... ] ]
CREATE ROLE name [ [ WITH ] option [ ... ] ]
#上面的两个命令都可以创建用户,不同的是CREATE USER创建的用户默认可以登录,而CREATE ROLE不可以登录
#除了CREATE USER默认创建出来的用户有LOGIN的权限,而CREATE ROLE创建出来的用户没有'LOGIN'的权限之外,CREATE RULE与CREATE USER没有其它任何的区别

#上面语法中的"option"可以是如下内容

SUPERUSER | NOSUPERUSER :表示创建出来的用户是否为超级用户。只有超级用户才能创建超级用户
CREATEDB | NOCREATEDB :指定创建出来的用户是否有执行"create database"的权限
CREATEROLE | NOCREATEROLE :指定创建出来的用户是否有创建其它角色的权限
INHERIT | NOINHERIT #如果创建一个用户拥有某一个或某几个角色,这时若指定INHERIT,则表示用户自动拥有相应角色的权限,否则这个用户没有该角色的权限
LOGIN | NOLOGIN #指定创建出来的用户是否有"LOGIN"的权限,可以临时地禁止一个用户地"LOGIN"权限,这是此用户就不能连接到数据库。
REPLICATION | NOREPLICATION
BYPASSRLS | NOBYPASSRLS
CONNECTION LIMIT connlimit :指定该用户可以使用地并发连接数量。默认值是-1,表示没有限制。
[ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL :用于控制存储在系统表里面地口令是否加密。
VALID UNTIL 'timestamp' :密码失效时间,如果不指定这个子句,那么口令将永远生效
IN ROLE role_name [, ...] :指定用户称为哪些角色地成员,请注意没有任何选项可以把新角色添加为管理员,必须使用独立地GRANT命令来做这件事情。
IN GROUP role_name [, ...] :与IN ROLE相同,是已过时地语法
ROLE role_name [, ...] :role_name将成为这个新建的角色的成员
ADMIN role_name [, ...] :role_name将有这个新建角色的WITH ADMIN OPTION权限
USER role_name [, ...] :与ROLE子句相同,但以过时
SYSID uid :此子句主要是为了SQL向下兼容,实际没有什么用户。

3.6.2 用户管理案例

#查看帮助
\h create user
\h alter user
\h drop user
\h create role
\h alter role
\h drop role

#以下两个命令用法相似
create user #创建的用户默认可以连接
create role #创建的用户默认无法连接

#修改用户
alter user

#删除用户
drop user

#显出所有用户和角色
#\du和\dg命令等价。原因是在PostgreSQL数据库中用户和角色部分的

范例:

#创建可以登录的用户和密码
postgres=# create user wang with password '123456';
CREATE ROLE

#创建不可登录的用户
postgres=# create role zhao with password '123456';
CREATE ROLE

#创建可以连接的用户
postgres=# create role li with login password '123456' valid until '2025-01-24';
CREATE ROLE

#创建管理员
postgres=# create role admin with superuser login password '123456';
CREATE ROLE

#创建复制用户
postgres=# create user repl replication login encrypted password '123456';
CREATE ROLE

#修改密码
postgres=# alter user wang with password '654321';
ALTER ROLE

#修改权限和密码
postgres=# alter user wang with nologin password '123';
ALTER ROLE
postgres=# alter user zhao with login;
ALTER ROLE

#删除用户
postgres=# drop user gf;
DROP ROLE

#查看用户信息
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 admin     | Superuser                                                  | {}
 li        | Password valid until 2025-01-24 00:00:00+08                | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 repl      | Replication                                                | {}
 wang      | Cannot login                                               | {}
 zhao      |                                                            | {}


#查看指定用户信息
postgres=# \du wang
            List of roles
 Role name |  Attributes  | Member of 
-----------+--------------+-----------
 wang      | Cannot login | {}

范例:修改postgres用户密码

#使用postgres用户登录(PostgerSQL安装后会自动创建postgres用户)
#登录postgresql数据库
#安全起见,修改数据库管理员postgres用户的密码
postgres=# alter user postgres with encrypted password '123456';
ALTER ROLE

3.6.3 权限管理

在PostgreSQL数据库中,每个数据库的对象(包括数据库)都有一个所有者,也就是说任何数据库对象都是属于某个用户的,所有者默认就拥有所有权限。所以不需要把对象的权限再赋给所有者。自己创建的数据库对象,自己当然有全部的权限。当然,所有者出于安全考虑也可以选择废弃一些自己的权限。再PostgreSQL数据库中,删除一个对象及任意修改它的权力是所有者固有的,不能被赋予或撤销。所有者也隐含地拥有把操作该对象地权限赋予给别人的权力。

一个用户的权限分为两类,一类是再创建用户时就指定的权限,这些权限如下:

  • 超级用户的权限
  • 创建数据库的权限
    是否允许LOGIN的权限

以上这些权限是创建用户时指定的,后续可使用ALTER ROLE命令来修改。

还有一类权限,是由命令GRANT和REVOKE来管理的,这些权限如下:

  • 在数据库中创建模式(SCHEMA)
  • 允许在指定的数据库中创建临时表连接某个数据库
  • 在模式中创建数据库对象,如创建表、视图函数等
  • 在一些表中做SELECT、UPDATE、INSERT、DELETE等操作等
#GRANT命令有两个作用
#1.让某个用户成为某个角色的成员,从而使其拥有角色的权限:
GRANT role_name [, ...] TO role_specification [, ...] [ WITH ADMIN OPTION ];

#2.把某些数据库逻辑结构对象的操作权限赋予某个用户(或角色),命令的格式如下:
GRANT some privileges ON database_object_type object_name TO role_name;
其中,"some_privileges"表示在这个数据库对象中的权限,"database_object_type"是数据库对象的类型,如"TABLE""SEQUENCE""SCHEMA"等。

PostgreSQL中的权限是按以下几个层次进行管理的:

  • cluster权限:实例权限通过pg_hba.conf配置
  • 管理赋在用户特殊属性上的权限,如超级用户的权限、创建数据库的权限、创建用户的权限、Login权限等
  • 在数据库中创建模式的权限
  • 表空间权限:通过grant/revoke控制权限操作表,物化视图,索引等
  • 在模式中创建数据库对象的权限,如创建表、创建索引,等等
  • 查询表、往表中插入数据、更新表、删除表中的数据的权限
  • 操作表中某些字段的权限

3.6.4 权限案例

范例:

#授权创建新数据库
hellodb=# alter user wang with createdb;
ALTER ROLE

#database权限设置
hellodb=# grant create on database testdb to wang;

#schema权限
hellodb=# alter schema wang owner to wang;
grant select,insert,update,delete on all tables in schema wang to wang;

#创建test的schema指定所有者为joe
create schema if not exists test authorization joe;

#object权限
grant select,insert,update,delete on testdb.t1 to wang;

#创建数据库并指定所有者用户
create user wang with password '123456';
create database zabbix owner wang;

范例:创建业务用户和授权

hellodb=# create database pinxixi;
hellodb=# \c pinxixi;
pinxixi=# create user wanrentuan with password '123456';

#方法1
pinxixi=# create schema wanrentuan;
pinxixi=# alter schema wanrentuan owner to wanrentuan;
#方法2
pinxixi=# create schema authorization wanrentuan;
#方法3
pinxixi=# grant select,insert,update,delete on all tables in schema wanrentuan to wanrentuan;
GRANT

范例:

#将创建一个名为"readonly"的用户
create user readonly with password '123456';
#将在public的schema下现有的所有表的SELECT权限赋给用户readonly
grant select on all tables in schema public to readonly;

4 PostgreSQL体系架构

4.1 体系架构概览

PostgreSQL和MySQL相似,也采用典型的C/S模型。

PostgreSQL体系结构分两部分

  • 实例instance
  • 磁盘存储

实例instance包括

  • 进程
  • 内存存储架构

在这里插入图片描述

4.2 进程和内存架构

PostgreSQL是进程架构模型,MySQL是线程架构模型。

在这里插入图片描述

4.2.1 进程

  • Postmaster 主进程
    • 它是整个数据库实例的主控制进程,负责启动和关闭该数据库实例。
    • 实际上,使用pg_ctl来启动数据库时,pg_ctl也是通过运行postgres来启动数据库的,只是它做了一些包装,更容器启动数据库。
    • 它是第一个PostgreSQL进程,此主进程还会fork出其它子进程,并管理它们。
    • 当用户和PostgreSQL建立连接时,首先是和Postmaster进程建立连接。首先,客户端会发出身份验证的信息给Postmaster进程,Postmaster进程根据消息中的信息进行身份验证判断,如果验证通过,他会fork出一个会话子进程为这个连接服务。
    • 当某个服务进程出现错误的时候,Postmaster主进程会自动完成系统的恢复。恢复过程中会停掉所有的服务进程,然后进行数据库数据的一致性恢复,等恢复完成后,数据库又可以接受新的连接。
    • 验证功能是通过配置pg_hba.conf和用户验证模块来提供。
    • postmaster程序是指向postgres的软链接
root@gf:~# ll /apps/pgsql/bin/postmaster 
lrwxrwxrwx 1 root root 8 Jan 10 13:31 /apps/pgsql/bin/postmaster -> postgres*	
  • BgWriter后台写进程
    • 为了提高插入、删除和更新数据的性能,当往数据库中插入或者更新数据时,并不会马上把数据持久化到数据文件中,而是先写入Buffer中
    • 该辅助进程可以周期性的把内存中的脏数据刷新到磁盘中
  • WalWriter 预写式日志进程
    • WAL时write ahead log的缩写,WAL log旧版中称为xlog,相当于MySQL中的Redo log
    • 预写式日志是在修改数据之前,必须把这些修改操作记录到磁盘中,这样后面更新实际数据时,就不需要实时的把数据持久化到文件中了。即使机器突然宕机或者数据库异常退出,导致一部分内存中的脏数据没有及时的刷新到文件中,在数据库重启后,通过读取WAL日志,并把最后一部分WAL日志重新执行一遍,就能恢复到宕机时的状态了
  • Checkpointer检查点进程
    • 检查点(Checkpoints)是事务序列中的点,保证在该点之前的所有日志信息都更新到数据文件中。
    • 在检查点时,所有脏数据页都冲刷并且向日志文件中写入一个特殊的检查点记录。在发生崩溃的时候,恢复器就知道应该从日志中的那个点(称做redo记录)开始做redo操作,因为在该记录前的对数据文件的任何修改都已经在磁盘上。在完成检查点处理之后,任何在redo记录之前的写日志段都不在需要,因此可以循环使用或者删除。在进行WAL归档的时候,这些日志在循环利用或者删除之前应该必须先归档保存
    • 检查点进程(CKPT)在特定事件自动执行一个检查点,通过向数据库写入进程(BgWriter)传递消息来启动检查点请求
  • AutoVacuum 自动清理进程
    • 执行delete操作时,旧的数据并不会立即被删除,在更新数据时,也不会在旧的数据上做更新,而是新生成一行数据。旧的数据只是被标识为删除状态,在没有并发的其他事务读到这些旧数据时,它们才会被清除掉
    • autovacuum lanucher负责回收垃圾数据的master进程,如果开启了autovacuum的话,那么postmaster会fork这个进程
    • autovacuum worker负责回收垃圾数据的worker进程,是lanucher进程fork出来的
  • PgStat统计数据收集进程
    • 此进程主要做数据的统计收集工作
    • 收集的信息主要用于查询优化时的代价估算。统计的数据包括对一个表或索引进行的插入、删除、更新操作,磁盘块读写的次数以及行的读次数等。
    • 系统表pg_statistic中存储了PgStat收集的各类统计信息
  • PgArch 归档进程
    • 默认没有此进程,开启归档功能后才会启动archiver进程
    • WAL日志文件会被循环使用,也就说WAL日志会被覆盖,利用PgArch进程会在覆盖前把WAL日志备份出来,类似于binlog,可用于备份功能。
  • SysLogger系统日志进程
    • 默认没有此进程,配置文件postgresql.conf设置参数logging_collect设置为"on"时,主进程才会启动SysLogger辅助进程
    • 它从Postmaster主进程、所有的服务进程以及其它辅助进程收集所有的stderr输出,并将这些输出写入到日志文件中。
  • startup 启动进程
    • 用户数据库恢复的进程
  • Session 会话进程
    • 每一个用户发起连接后,一旦验证成功,postmaster进程就会fork一个新的子进程负责连接此用户
    • 通常表现为进程形式:postgres postgres [local] idle

案例:查看进程

在这里插入图片描述

root@gf:~# ps -auxf |grep postgres
root        2689  0.0  0.0  61756  3900 pts/0    S    09:23   0:00  |                   \_ su - postgres
postgres    2690  0.0  0.1  21604  5328 pts/0    S+   09:23   0:00  |                       \_ -su
root        3914  0.0  0.0  13140  1096 pts/1    S+   11:58   0:00                      \_ grep --color=auto postgres
postgres    2758  0.0  0.4 172096 17960 ?        Ss   09:25   0:00 /apps/pgsql/bin/postgres -D /pgsql/data
postgres    2760  0.0  0.1 172228  7700 ?        Ss   09:25   0:00  \_ postgres: checkpointer 
postgres    2761  0.0  0.1 172096  4980 ?        Ss   09:25   0:00  \_ postgres: background writer 
postgres    2762  0.0  0.1 172096  7476 ?        Ss   09:25   0:00  \_ postgres: walwriter 
postgres    2763  0.0  0.1 172772  5396 ?        Ss   09:25   0:00  \_ postgres: autovacuum launcher 
postgres    2764  0.0  0.0  27188  3272 ?        Ss   09:25   0:00  \_ postgres: stats collector 
postgres    2765  0.0  0.0 172528  3468 ?        Ss   09:25   0:00  \_ postgres: logical replication launcher 

范例:开启归档后在查看进程
在这里插入图片描述

postgres@gf:~$ ps -auxf |grep postgres
root        2011  0.0  0.0  61756  3752 pts/0    S    15:16   0:00                      \_ su - postgres
postgres    2012  0.0  0.1  21472  5372 pts/0    S    15:16   0:00                          \_ -su
postgres    2143  0.0  0.0  38716  3796 pts/0    R+   15:17   0:00                              \_ ps -auxf
postgres    2144  0.0  0.0  13140  1040 pts/0    S+   15:17   0:00                              \_ grep --color=auto postgres
postgres    2131  0.0  0.4 172096 17852 ?        Ss   15:17   0:00 /apps/pgsql/bin/postgres -D /pgsql/data
postgres    2136  0.0  0.0 172096  2464 ?        Ss   15:17   0:00  \_ postgres: checkpointer 
postgres    2137  0.0  0.0 172096  2464 ?        Ss   15:17   0:00  \_ postgres: background writer 
postgres    2138  0.0  0.0 172096  2464 ?        Ss   15:17   0:00  \_ postgres: walwriter 
postgres    2139  0.0  0.1 172772  5276 ?        Ss   15:17   0:00  \_ postgres: autovacuum launcher 
postgres    2140  0.0  0.0 172096  2528 ?        Ss   15:17   0:00  \_ postgres: archiver 
postgres    2141  0.0  0.0  27188  3156 ?        Ss   15:17   0:00  \_ postgres: stats collector 
postgres    2142  0.0  0.0 172528  3400 ?        Ss   15:17   0:00  \_ postgres: logical replication launche

4.2.2 内存结构

PostgreSQL的内存空间包括共享内存和本地内存两部分

  • 共享内存
    • PostgreSQL启动后,会生成一块共享内存,共享内存主要用做数据块的缓冲区,以便提高读写性能。WAL日志缓冲区和CLOG(Commit log)缓冲区也存在于共享内存中。除此以外,一些全局信息也保存在共享内存中,如进程信息、锁的信息、全局统计信息等。
    • PostgreSQL 9.3之前的版本与Oracle数据库一样,都是使用"system V"类型的共享内存,但到PostgreSQL9.3之后,PostgreSQL使用mmap()方式共享内存,好处能使用较大的共享内存。
    • 可以通过配置postgresql.conf文件中share_buffers指定,默认128M,建议是内存的50%

在这里插入图片描述

  • 本地内存
    • 后台服务进程除访问共享内存外,还会申请分配一些本地内存,以便暂存一些不需要全局存储的数据。都可以通过在配置postgresql.conf文件中指定
    • 这些内存缓存区主要有以下几类
      • temp_buffers: 用于访问临时表的本地缓冲区,默认为8M
      • work_mem: 内存排序操作和Hash表在使用临时磁盘文件之前使用的内存缓冲区,默认为4M
      • maintenance_work_mem:在维护性操作(比如VACUUM、CREATE INDEX和ALTERTABLE ADD FOREIGN KEY等)中使用的内存缓冲区,默认为64M

范例:查看内存空间

postgres=# show shared_buffers;
 shared_buffers 
----------------
 128MB
(1 row)

postgres=# show maintenance_work_mem;
 maintenance_work_mem 
----------------------
 64MB
(1 row)

postgres=# show work_mem;
 work_mem 
----------
 4MB
(1 row)

4.3 数据更新过程

在这里插入图片描述

  • 先将数据库文件中的更改的数据加载至内存
  • 在内存更新数据
  • 将日志写入内存WAL的缓冲区
  • 将日志提交,将日志写入操作系统cache
  • 同步日志到磁盘
  • 后台写数据库的更新后的数据到操作系统cache
  • 写完数据后,更新检查点checkpoint
  • 同步数据到磁盘

当数据库中数据发生变更时:
change发生时:先要将变更后内容计入wal buffer中,再将变更后的数据写入data buffer;
commit发生时:wal buffer中数据刷新到磁盘;
checkpoint发生时:将所有data buffer刷新到磁盘

4.4 数据库目录结构

4.4.1 数据库目录介绍

在这里插入图片描述

数据库数据存放在环境变量PGDATA指向数据目录。这个目录是在安装时指定的,所以在安装时需要指定一个合适的目录作为数据目录的根目录,而且,每一个数据库实例都要有一个对应的目录。目录的初始化是使用initdb来完成的。

初始化完成后,PGDATA数据目录下就会生成三个配置文件。

postgresql.conf #数据库实例的主配置文件,基本上所有的配置参数都在此文件中
pg_hba.conf #认证配置文件,配置了允许哪些IP的主机访问数据库,认证方法是什么等信息
pg_ident.conf #认证方式ident的用户映射文件

此外在PGDATA目录下还会生成如下一些子目录

base #默认表空间的目录,每个数据库都对应一个base目录下的子目录,每个表和索引对应一个独立文件
global #这个目录对应pg_global表空间,存放实例中的共享对象
pg_clog #存储事务提交状态数据
pg_hba.conf #数据库访问控制文件
pg_log #数据库系统日志目录,在查询一些系统错误时就可查看此目录下日志文件。(根据配置定义,可能没有这个目录)
pg_xact #提交日志commit log的目录,pg 9之前叫pg_clog
pg_multixact #共享行锁的事务状态数据
pg_notify #异步消息相关的状态数据pg_serial #串行隔离级别的事务状态数据
pg_subrans #子事务状态数据
pg_stat #统计信息的存储目录。关闭服务时,将pg_stat_tmp目录中的内容移动至此目录实现保存
pg_stat_tmp #统计信息的临时存储目录。开启数据库时存放统计信息
pg_tblsp #存储了指向各个用户自建表空间实际目录的链接文件
pg_twophase #使用两阶段提交功能时分布式事务的存储目录
pg_wal #WAL日志的目录,早期版本目录为PG_xlog
PG_VERSION #数据库版本
postmaster.opts #记录数据库启动时的命令行选项
postmaster.pid #数据库启动的主进程信息文件,包括PID,SPGDATA目录,数据库启动时间,监听端口,socket文件路径,临听地址,共享内存的地址信息(ipsc可查看),主进程状态。

范例:

postgres@gf:~$ ll /pgsql/data
total 140
drwx------ 19 postgres postgres  4096 Jan 24 15:17 ./
drwxr-xr-x  4 root     root      4096 Jan 14 10:24 ../
drwx------ 11 postgres postgres  4096 Jan 24 11:01 base/
drwx------  2 postgres postgres  4096 Jan 24 15:18 global/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_commit_ts/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_dynshmem/
-rw-------  1 postgres postgres  4603 Jan 16 14:57 pg_hba.conf
-rw-------  1 postgres postgres  1636 Jan 10 13:40 pg_ident.conf
drwx------  4 postgres postgres  4096 Jan 24 15:22 pg_logical/
drwx------  4 postgres postgres  4096 Jan 10 13:40 pg_multixact/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_notify/
drwx------  3 postgres postgres  4096 Jan 21 13:48 pg_replslot/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_serial/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_snapshots/
drwx------  2 postgres postgres  4096 Jan 24 15:17 pg_stat/
drwx------  2 postgres postgres  4096 Jan 24 17:12 pg_stat_tmp/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_subtrans/
drwx------  2 postgres postgres  4096 Jan 21 15:33 pg_tblspc/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_twophase/
-rw-------  1 postgres postgres     3 Jan 10 13:40 PG_VERSION
drwx------  3 postgres postgres  4096 Jan 20 13:58 pg_wal/
drwx------  2 postgres postgres  4096 Jan 10 13:40 pg_xact/
-rw-------  1 postgres postgres    88 Jan 10 13:40 postgresql.auto.conf
-rw-------  1 postgres postgres 28805 Jan 24 15:17 postgresql.conf
-rw-------  1 postgres postgres    44 Jan 24 15:17 postmaster.opts
-rw-------  1 postgres postgres    69 Jan 24 15:17 postmaster.pid
-rw-rw-r--  1 postgres postgres  2753 Jan 10 16:19 serverlog

4.4.2 postgresql.conf配置项

PostgreSQL的配置参数是在postgres.conf文件中集中管理的,这个文件位于数据库实例的目录下$PGDATA

  • 此文件中的每个参数配置项的格式都是"参数名=参数值"
  • 配置文件中可以使用"#"注释
  • 所有配置项的参数名都是大小写不敏感的
  • 参数值有以下物种类型
    • 布尔:布尔值都是大小写无关的,可以是on、off、true、false、yes、no、1、0.
    • 整数:数值可以指定单位。如一些内存配置的参数可以指定KB、MB、GB等单位
    • 另外还支持浮点数、字符串、枚举
  • postgres.conf文件中可以使用include指令包含其它文件中的配置内容,如:include filename,如果指定被包含的文件名不是绝对路径,那么就相对于当前配置文件所在目录的相对路径。此外,包含还可以被嵌套
  • 所有的配置参数都在系统视图pg_settings中
  • $PGDATA目录下如果含有postgres.conf和postgresql.auto.conf,而postgresql.auto.conf的优先级高于postgresql.conf,即如果一个参数同时存在postgres.auto.conf和postgres.conf里面,系统会先读postgresql.auto.conf的参数配置

常用配置说明:

listen_addresses = '*' #监听客户端的地址,默认为本地的,需要修改为*或者0.0.0.0
port = 5432 #pg端口,默认为5432
max_connections = 100 #最大连接数,默认100
#unix_socket_directories = '/tmp' #socket文件的位置,默认在/tmp下面
shared_buffers = 128MB #数据缓存区,建议值1/4--1/2主机内存,和Oracle的buffer cache类似
maintenance_work_mem = 64MB	 #维护工作内存,用于vacuum,create index,reindex等。建议值(1/4主机内存)/autovacuum_max_workers
max_worker_processes = 8 #总worker数,也就是进程数
max_parallel_workers_per_gather = 2 #单条QUERy中,每个node最多允许开启的并行计算worker数
wal_level = logical #wal级别,版本11+默认是replica
wal_buffers #类似Oracle的log buffer
checkpoint_timeout = 5min #checkpoint时间间隔
max_wal_size = 1GB #控制wal最大数量
min_wal_size = 80MB #控制wal最小数量
archive_mode = on		
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'#开启归档命令	 
autovacuum #开启自动vacuum

范例:

postgres=# \d pg_settings;
               View "pg_catalog.pg_settings"
     Column      |  Type   | Collation | Nullable | Default 
-----------------+---------+-----------+----------+---------
 name            | text    |           |          | 
 setting         | text    |           |          | 
 unit            | text    |           |          | 
 category        | text    |           |          | 
 short_desc      | text    |           |          | 
 extra_desc      | text    |           |          | 
 context         | text    |           |          | 
 vartype         | text    |           |          | 
 source          | text    |           |          | 
 min_val         | text    |           |          | 
 max_val         | text    |           |          | 
 enumvals        | text[]  |           |          | 
 boot_val        | text    |           |          | 
 reset_val       | text    |           |          | 
 sourcefile      | text    |           |          | 
 sourceline      | integer |           |          | 
 pending_restart | boolean |           |          | 


postgres=# select name,short_desc,setting from pg_settings where name like 'listen_addresses';
       name       |                     short_desc                     | setting 
------------------+----------------------------------------------------+---------
 listen_addresses | Sets the host name or IP address(es) to listen to. | *
(1 row)


#查看运行时参数
postgres=# show listen_addresses;
 listen_addresses 
------------------
 *
(1 row)


#动态修改配置
postgres=# set timezone="Asia/Shanghai";

范例:postgresql.auto.conf 文件优先于postgres.conf

4.4.3 pd_ident.conf

pg_indent.conf是用户映射配置文件。结合pg_hba.conf文件,method为ident可以用特定的操作系统用户已指定的数据库用户身份登录数据库。

这个文件记录者与操作系统用户匹配的数据库用户,如果某操作系统用户在本文件中没有映射用户,则默认的映射数据库用户与操作系统用户同名。比如,服务器上有名为user1的操作系统用户,同时数据库库上也有同名的数据库用户user1,user1登录操作系统后可以直接输入psql,以user1数据库用户身份登录数据库且不需密码。

范例:操作系统用户和数据库用户不同名

#pg_ident.conf如下实现操作系统test用户映射为数据库用户dba
# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
map1            test                    dba

#pg_hba.conf如下:
local      all     all ident     map=map1

范例:操作系统用户和数据库用户同名

useradd -s /bin/bash -m dba

postgres=# create user dba with password '123456';

root@gf:~# cat /pgsql/data/pg_hba.conf
local   all             all             ident

root@gf:~#  pg_ctl restart
root@gf:~# su - dba
dba@gf:~# psql postgres
postgres=>

4.4.4 数据文件

PostgreSQL中的每个索引和表都是一个单独的文件,称为Segment。默认是每个大于1G的Segment会 被分割pg_class.efilenode.1这样的文件。Segment的大小可以在initdb时通过选项–with-segsize=SEGSIZE指定

注意:truncate表之后relfilenode会变。对应的物理文件名字也会变。

Segment物理位置

$PGDATA/BASE/DATABASE_OID/PG_CLASS.RELFILENODE

范例:数据文件路径

root@gf:~/postgresql-14.2# ./configure --help|grep size
  --with-blocksize=BLOCKSIZE
                          set table block size in kB [8]
  --with-segsize=SEGSIZE  set table segment size in GB [1]
  --with-wal-blocksize=BLOCKSIZE
                          set WAL block size in kB [8]


#查看数据目录路径
postgres=# show data_directory;
 data_directory 
----------------
 /pgsql/data
(1 row)

#查看数据库的OID
postgres=# select oid,datname from pg_database;
  oid  |  datname  
-------+-----------
 12974 | postgres
     1 | template1
 12973 | template0
 16535 | sample_1
(4 rows)

#查看表的node
gf=# select relfilenode from pg_class where relname='tb1';
 relfilenode 
-------------
       16547
(1 row)


#查看指定表的目录路径
gf=# select pg_relation_filepath('tb1');
 pg_relation_filepath 
----------------------
 base/16546/16547
(1 row)


root@gf:~# ll /pgsql/data/base/16546/16547 
-rw------- 1 postgres postgres 0 Jan 27 10:59 /pgsql/data/base/16546/16547

4.4.5 控制文件

控制文件存放了数据库当前的状态,存放在PGDATA/global/pg_control

#PG14控制文件
root@gf:~# file /pgsql/data/global/pg_control 
/pgsql/data/global/pg_control: data

#查看控制文件内容
root@gf:~# pg_controldata $PGDATA
pg_control version number:            1300
Catalog version number:               202107181
Database system identifier:           7458157620107561034
Database cluster state:               in production
pg_control last modified:             Mon 27 Jan 2025 10:59:51 AM CST
Latest checkpoint location:           0/31001378
Latest checkpoint's REDO location:    0/31001340
Latest checkpoint's REDO WAL file:    000000010000000000000031
Latest checkpoint's TimeLineID:       1
Latest checkpoint's PrevTimeLineID:   1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID:          0:1061
Latest checkpoint's NextOID:          24738
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        727
Latest checkpoint's oldestXID's DB:   1
Latest checkpoint's oldestActiveXID:  1060
Latest checkpoint's oldestMultiXid:   1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint:            Mon 27 Jan 2025 10:59:51 AM CST
Fake LSN counter for unlogged rels:   0/3E8
Minimum recovery ending location:     0/0
Min recovery ending loc's timeline:   0
Backup start location:                0/0
Backup end location:                  0/0
End-of-backup record required:        no
wal_level setting:                    logical
wal_log_hints setting:                off
max_connections setting:              100
max_worker_processes setting:         8
max_wal_senders setting:              10
max_prepared_xacts setting:           0
max_locks_per_xact setting:           64
track_commit_timestamp setting:       off
Maximum data alignment:               8
Database block size:                  8192
Blocks per segment of large relation: 131072
WAL block size:                       8192
Bytes per WAL segment:                16777216
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        1996
Size of a large-object chunk:         2048
Date/time type storage:               64-bit integers
Float8 argument passing:              by value
Data page checksum version:           0
Mock authentication nonce:            151fb4498297dbefe4db1e0366360fbe9e233541f59011bba4c4884cb48635e1

4.4.6 日志文件

4.4.6.1 日志种类
  • 运行日志:$PGDATA/log(pg10之前为PGDATA/pg_log)默认不存在,需要开启配置项logging_controller
  • 在线重做日志:PGDATA/pg_wal(pg10之前为$PGDATA/pg_xlog)
  • 事务提交日志:PGDATA/pg_xact(pg10之前为PGDATA/pg_clog)
  • 服务器日志:可以在启动的时候指定: pg_ctl start -l ./logfile
4.4.6.2 运行日志
4.4.6.2.1 运行日志配置项
logging_collector: 这个参数启用日志收集器,它是一个捕捉被发送到stderr日志消息的后台进程,并且它会将这些消息重定向到日志文件中:默认为OFF,修改参数需要重启。

log_destination: 有三种输出方法,stderr,csvlog,syslog:在windows上还支持eventlog。默认时stderr,如果使用csvlog的话,logging_connector必须开启。也可以同时使用csvlog和stderr,会记录两种格式的日志。

log_directory:指定日志的存放位置,默认是$PGDATA/log

log_filename:日志的命名格式,默认是postgresql-%Y-%m-%d_%H%M%S.log,支持strftime格式

log_file_mode:当logging_collector被启用时,这个参数设置日志文件的权限(在windows上这个参数将被忽略)。这个参数值应当是一个数字形式的模式,它可以被chmod和umask系统掉调用接受(要使用通常的十进制格式,该数字必须以一个0开始)。默认的权限是0600,表示只有服务器拥有者才能读取或写入日志。其它常用的设置是0640,它允许拥有者的组成员读取文件。不过要注意你需要修改log_directory为将文件存储在集簇数据目录之外的某个位置,才能利用这个设置。

log_rotation_age:当logging_collector被启动时,这个参数决定一个个体日志文件的最长生命期。当这些分钟过去后,一个新的日志文件将被创建。将这个参数设置为零将禁用基于时间的新日志文件创建。

log_rotation_size: 当logging_collector被启用时,这个参数决定一个个体日志文件的最大尺寸。当这么多千字节被发送到一个日志文件后,将创建一个新的日志文件。将这个参数设置为零将禁用基于尺寸的新日志文件创建。

log_truncate_on_rotation:默认为off,设置为on的话,如果新建一个同名的日志文件,则会清空原来的文件,再写入日志,而不是再后面追加。

log_min_messages:控制哪些消息级别,被写入到服务器日志。有效值是DEBUG5、DEBUG4、DEBUG3、DEBUG2、DEBUG1、INFO、NOTICE、WARNING、ERROR、LOG、FATAL和PANIC。每个级别都包括以后的所有级别。级别越靠后,被发送的消息越少。默认值是WARNING。

log_min_error_statement:控制哪些导致错误情况的SQL语句被记录在服务器日志中。默认值是ERROR,要有效地关闭记录错误语句,将这个参数设置为PANIC。

log_min_duration_statement:相当于mysql地long_query_time,记录慢SQL,超过这个时间地SQL将会被记录到日志里。以ms为单位。

log_checkpoints: 导致检查点和重启点被记录在服务器日志中。一些统计信息也被包括在日志消息中,包括写入缓冲区地数据和它们所花的时间。

log_connections: 导致每一次尝试对服务器的连接被记录,客户端认证的成功完成也会被记录。只有超级用户能在会话开始时更改这个参数,在会话中它不能被更改。默认为off。

log_disconnections: 导致会话终止也会被记录。日志输出提供的信息类似于log_connections,不过还外加会话的持续时间。只有超级用户能在会话开始时更改这个参数,在会话中它不能被更改。默认为off。

log_duration: 导致每一个完成的语句的持续时间被记录。默认值是off。如果log_duration为on并且log_min_duration_statement为正值,所有持续时间会被记录,但是只有超过阈值的语句才会被记录查询文本。这种行为有助于在高负载安装中收集统计信息。


log_error_verbosity: 有效值是TERSE、DEFAULT和VERBOSE,默认值是default,控制每条日志信息的详细程度,VERBOSE输出包括SQLSTATE错误码,以及产生错误的源代码文件名、函数名和行号。

log_hostname:默认情况下,连接日志消息只显示连接主机的IP地址。打开这个参数将导致也记录主机名。注意根据你的主机名解析设置,这可能会导致很微小的性能损失。


log_line_prefix:设置日志输出格式(能够记录时间,用户名称,数据库名称,客户端IP和端口,方便定位问题)默认值是'%m [%p]',他记录时间戳和进程ID

log_lock_waits: 控制当一个会话为获得一个锁等到超过deadlock_timeout时,是否产生一个日志消息。这有助于决定是否锁等待造成了性能低下。默认值为off。

log_statement:控制哪些SQL被记录。有效值是none(off)、ddl、mod和all(所有语句)。默认值为none


log_replication_commands:每一个复制命令都被记录在服务器日志中。

log_temp_files: 控制记录临时文件名和尺寸。临时文件可以被创建用来排序、哈希和存储临时查询结果。一个零值记录所有临时文件信息,而正值只记录尺寸大于或等于指定千兆字节数的文件。默认设置为-1,它禁用这中记录。

log_timezone: 设置在服务器日志中写入的时间戳的时区。默认值为GMT。
4.4.6.2.2 将csv格式运行日志存储数据库
vim postgresql.conf
log_destination = 'csvlog'
logging_collector = on

在这里插入图片描述

4.4.6.3 在线WAL日志

Online WAL(WRITE-AHEAD LOG)日志功能是为了保证崩溃后的安全,如果系统崩溃,可以"重放"从最后一次检查点以来的日志项来恢复数据库的一致性。但是为存在日志膨胀的问题,相当于MySQL的事务日志redo log

参考文档:

https://www.postgresql.org/docs/14/runtime-config-wal.html
4.4.6.3.1 Online WAL日志文件位置
wal文件存放在$PGDATA/pg_wal下。PG10之前pg_xlog
4.4.6.3.2 设置Online WAL日志的大小
#初始化实例时,可以指定单个WAL文件的大小,默认16M
initdb --wal-segsize=SIZE

#WAL日志总的大小默认值
max_wal_size = 1GB
min_wal_size = 80MB

max_wal_size(integer)
#在自动WAL检查点之间允许WAL增长到的最大尺寸。这是一个软限制,在特殊情况下WAL尺寸可能会超过max_wal_size,例如在高度负荷下、archive_command失败或者高的wal keep_segments设置。如果指定值时没有单位,则以兆字节为单位。默认为1GB。增加这个参数可能导致崩溃恢复所需的时间。这个参数只能在postgresql.conf或者服务器命令行中设置。
min_wal_size(integer)
#只要WAL磁盘用量保持在这个设置之下,在检查点时旧的WAL文件总是被回收以便未来使用,而不是直接被删除。这可以被用来确保有足够的WAL空间被保留来应付WAL使用的高峰,例如运行大型的批处理任务。如果指定值时没有单位,则以兆字节为单位。默认为80MB。这个参数只能在postgresql.conf或者服务器命令行中设置。

#注意:PG9.4之前版本中的checkout_segments可以指定在自动的WAL检查点之间的日志文件段的最大数量(通常每个段16M字节)。缺省是3.从PG9.5开始淘汰此配置项,用max_wal_size和min_wal_size代替。
4.4.6.3.3 LSN和Online WAL文件命名格式

LSN:Log Sequence Number 用于记录WAL文件当前的位置,这是WAL日志唯一的、全局标识。

WAL 日志中写入是有顺序的,所以必须得记录WAL日志得写入顺序。而LSN就是负责给每条产生得WAL日志记录唯一得编号

WAL日志LSN编号规则:

高32位/低32位

WAL文件名称为16进制的24个字符组成,每8个字符一组

每组的意义如下:

00000001 00000000 0000002D
时间线    逻辑id   物理id
其中前8位:00000001 表示timeline
中间8位: 00000000表示login,即LSN高32位
最后8位:0000002D表示logseg,即LSN低32位/(2**24)的值,即低32位中最高8位,16进制的高2位。

范例:

#查看当前LSN
postgres=# select pg_current_wal_lsn();
 pg_current_wal_lsn 
--------------------
 0/31019FF8
(1 row)

#查看当前LSN对应的WAL日志文件
postgres=# select pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000031
(1 row)
4.4.6.3.4 查看LSN和WAL文件对应关系

范例:

#查看当前事务ID
postgres=# select txid_current();
 txid_current 
--------------
         1062
(1 row)

#查看当前LSN号
postgres=# select pg_current_wal_lsn();
 pg_current_wal_lsn 
--------------------
 0/3101A078
(1 row)

#查看当前LSN对应的WAL日志文件
#WAL日志文件中的最后8位的logseg前6位始终是0,最后两位是LSN的低32位的前两位。如上例中logseg最后两位是31,LSN低32位的前两位也是31
postgres=# select pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000031
(1 row)

#查看当前WAL日志偏移量
#LSN在WAL日志文件中的偏移量即LSN低32位中后24位对应的十进制。如上面01A078对应十进制即下面的106848
postgres=# select pg_walfile_name_offset(pg_current_wal_lsn());
      pg_walfile_name_offset       
-----------------------------------
 (000000010000000000000031,106848)
(1 row)

#按时间排序显示WAL文件名
postgres=# select * from pg_ls_waldir() order by modification asc;
           name           |   size   |      modification      
--------------------------+----------+------------------------
 000000010000000000000036 | 16777216 | 2025-01-20 13:44:05+08
 00000001000000000000004B | 16777216 | 2025-01-20 13:44:05+08
 00000001000000000000003D | 16777216 | 2025-01-20 13:44:06+08
 00000001000000000000003E | 16777216 | 2025-01-20 13:44:06+08
 000000010000000000000034 | 16777216 | 2025-01-20 13:44:06+08
 000000010000000000000033 | 16777216 | 2025-01-20 13:44:07+08
 000000010000000000000048 | 16777216 | 2025-01-20 13:44:07+08
 000000010000000000000041 | 16777216 | 2025-01-20 13:44:08+08
 000000010000000000000040 | 16777216 | 2025-01-20 13:44:08+08
 000000010000000000000037 | 16777216 | 2025-01-20 13:44:09+08
 000000010000000000000038 | 16777216 | 2025-01-20 13:44:09+08
 000000010000000000000043 | 16777216 | 2025-01-20 13:44:10+08

4.4.6.3.5 切换WAL日志
#默认WAL文件达到16M,自动切换另一个WAL
postgres=# select pg_switch_wal();
 pg_switch_wal 
---------------
 0/3101A178
(1 row)

#PG10版本前用下面命令
select pg_switch_xlog();
4.4.6.3.6 查看WAL文件内容

命令pg_waldump可以查看WAL日志的具体内容

注意:pg_waldump执行结果中tx:后面的数字是txid,及事务ID,WAL中同一个事务的记录此值是相同的

root@gf:/pgsql/data# pg_waldump pg_wal/000000010000000000000031
rmgr: XLOG        len (rec/tot):    114/   114, tx:          0, lsn: 0/31000028, prev 0/30001480, desc: CHECKPOINT_SHUTDOWN redo 0/31000028; tli 1; prev tli 1; fpw true; xid 0:1060; oid 16546; multi 1; offset 0; oldest xid 727 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 0; shutdown
rmgr: Standby     len (rec/tot):     50/    50, tx:          0, lsn: 0/310000A0, prev 0/31000028, desc: RUNNING_XACTS nextXid 1060 latestCompletedXid 1059 oldestRunningXid 1060
rmgr: Standby     len (rec/tot):     50/    50, tx:          0, lsn: 0/310000D8, prev 0/310000A0, desc: RUNNING_XACTS nextXid 1060 latestCompletedXid 1059 oldestRunningXid 1060
rmgr: XLOG        len (rec/tot):    114/   114, tx:          0, lsn: 0/31000110, prev 0/310000D8, desc: CHECKPOINT_ONLINE redo 0/310000D8; tli 1; prev tli 1; fpw true; xid 0:1060; oid 16546; multi 1; offset 0; oldest xid 727 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 1060; online
rmgr: Standby     len (rec/tot):     50/    50, tx:          0, lsn: 0/31000188, prev 0/31000110, desc: RUNNING_XACTS nextXid 1060 latestCompletedXid 1059 oldestRunningXid 1060
rmgr: XLOG        len (rec/tot):     30/    30, tx:          0, lsn: 0/310001C0, prev 0/31000188, desc: NEXTOID 24738

4.4.6.3.7 创建恢复点
事先创建恢复点,将来可用它进行还原,相当于快照
postgres=# select pg_create_restore_point('test-restore-point');
4.4.6.4 归档WAL日志

归档日志记录的是checkpoint前的WAL日志,即数据的历史日志,即把pg_wal里面的在线日志备份出来,功能上归档日志相当于MySQL的二进制日志。

生成环境中为了保证数据高可用性,通常需要开启归档,当系统故障后可以通过归档的日志文件对数据进行恢复。

#配置归档需要开启如下参数:
wal_level = replica
#该参数的可选的值有minimal,replica和logical,wal的级别依次增高,在wal的信息也越多。由于minimal这一级别的wal不包含从基础的备份和wal日志重建数据的足够信息,在该模式下,无法开启wal日志归档。

#从PostgreSQL 10开始,默认使用的replica此级别,也建议使用此级别,之前版本默认是最小级别minimal

archive_mode = on	
#上述参数为on,表示打开归档备份,可选的参数为on,off,always默认值为off,所以要手动打开,需要重启服务生效
#在PostgreSQL中配置归档的方法是配置参数archive_command,参数的配置值可以是Unix命令,此命令把WAL日志文档拷贝到其它地方
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'	
archive_command = 'DIR=/archive/`data +%F`;[-d $DIR] || mkdir -p $DIR;cp %p $DIR/%f'
#该参数的默认值是一个空字符串,值可以是一条shell命令或者一个复杂的shell脚本
#用"%p"表示将要归档文件包含完整路径的信息的文件名
#用"%f"代表不包含路径信息的wal文件的文件名

#注意:wal_level和archive_mode参数修改都需要重新启动数据库才可以生效,而修改archive_command则不需要。

#无论当时是否需要归档,这要建议将上面两个参数开启。

实例:本地归档备份

archive_mode = on
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

#上面的命令中"archive_mode = on"表示打开归档备份
#参数archive_command的配置值是一个Unix的cp命令
#命令中 %p表示在线WAL日志文件的全路径名称
#%f表示不包括路径的WAL日志文件名

在实际执行备份时,PostgreSQL会把%p替换成实际在线WAL日志文件的全路径名,并把%f替换成不包括路径的WAL日志名。

使用操作系统命令scp还可以把WAL日志拷贝到其它机器上,从而实现对归档日志进行远程备份。

示例:远程归档备份

archive_mode = on
achive_command = "scp %p postgres:172.16.10.21:/pgsql/backup/%f'

使用上面拷贝WAL文件的方式来同步主、备数据库之间数据时,备库会落后主库一个WAL日志文件,具体落后多长时间取决于主库上生成一个完整的WAL文件所需要的时间。

范例:启用归档

#配置参数
wal_level = logical
archive_mode = on                                           
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' 

mkdir /mnt/server/archivedir
chown -R postgres. /mnt/server/archivedir

#重启数据库
pg_ctl restart

5 PostgreSQL备份恢复

5.1 备份说明

防止数据丢失的最重要方法就是备份。这些数据丢失有的是因硬件损坏导致的,有的是因认为原因(如误操作)导致的,也有因为应用程序的bug而误删除数据等情况

备份的内容包括:

  • 数据(配置文件)
  • 归档WAL日志
  • 表空间目录

数据库备份方式

  • 逻辑备份:适用于跨版本和跨平台的备份恢复
  • 物理备份:适用于小版本的恢复,但不支持跨平台和大版本

5.2 逻辑备份

PostgreSQL提供了pg_dump、pg_dumpall命令进行数据库的逻辑备份。

两者的功能差不多,只是pg_dumpall是将一个PostgreSQL数据库集群全部转储到一个脚本文件中,而pg_dump命令可以选择一个数据库或部分表进行备份。

另外利用COPY命令也能对表和SQL子集进行备份,实现表的还原。

5.2.1 pg_dump和pg_dumpall

pg_dump是postgreSQL提供的一个非常有用的数据库备份工具。它甚至可以在数据库正在使用的时候进行完整一致的备份。pg_dump工具执行时,可以将数据库备份成一个文本文件和归档文件,该文件中实际上包含了多个CREATE和INSERT语句,使用这些语句可以重新创建表和插入数据。

pg_dumpall工具可以存储一个数据库集群里的所有数据库到一个脚本文件。本质上pg_dumpall是通过对数据库集群里的每一个数据库调用pg_dump实现这个功能

pg_dumpall还可以备份出所有数据库公用的全局元数据库对象。这些信息包括:数据库用户和组,密码以及适用于整个数据库的访问权限。而pg_dump并不保存这些对象。

pg_dump可生成归档格式的备份文件,然后与pg_restore配合使用,从而提供一种灵活的备份和恢复机制。

pg_dump可以将整个数据库备份到一个归档文件中,而pg_restore则可从这个归档格式的备份文件中选择性地恢复部分表或数据库对象。归档格式地备份文件又分为两种,最灵活地输出文件格式时"custom"自定义格式(使用命令项参数-Fc来指定),它允许对归档元素进行选取和重新排列,并且默认时是压缩的;另一种格式是tar格式(使用命令项参数-Fc来指定),这种格式的文件不是压缩的,并且加载时不能重新排列,但那时它也很灵活,可以用标准UNIX的tar工具进行处理。

pg_dumpall只支持文本格式

pg_dump的具体语法如下:

pg_dump [OPTION]... [DBNAME]
#连接选项和psql基本相同,pg_dump连接选项的参数如下。
-h host或--host=host #指定运行服务器的主机名。如果以斜杠开头,则被用作到UNIX域套接字的路径。默认情况下,如果设置了SPGHOST环境变量,则从此环境变量中获取,否则尝试一个UNIX域套接字连接。
-p port或--port=port #指定服务器正在侦听的TCP端口或本地UNIX域套接字文件的扩展。默认情况下,如果设置了$PGDATA环境变量,则从此环境变量中获取,否则取值为默认端口5432(编译时可以改变这个默认端口)。

-U username或--username=username指定要连接的用户名
-w或--no-password #从不提示密码、密码可以通过其他方式如 ~/.pgpass文件获取
dbname #指定连接的数据库名,实际上也是要备份的数据库名。如果没有使用这个参数,则使用环境变量SPGDATABASE。如果SPGDATABASE也没声明,那么可使用发起连接的用户名。

#pg_dump专用选项
-a 或 --data-only #那个选项只是对纯文本格式有意义。只输出数据,不输出数据定义的SQL语句
-b 或--blobs #在转储中是否包含大对象。除非指定了选择性转储的选项--schema、--table、--schema-only开关,否则默认会转储大对象。此选项仅用于选择性转储时控制是否转储大对象。
-c 或--clean #这个选项只对纯文本格式有意义。指定输出的脚本中是否生成清理该数据库对象语句(如drop table命令)
-C或--create #这个选项只对纯文本格式有意义。指定脚本中是否输出一条create database语句和连接到该数据库的语句。一般在备份的元数据库域恢复的目标数据库的名称一致时,才指定这个参数。

-E encoding或--encoding=encoding #以指定的字符集编码创建转储。默认转储是依据数据库编码创建的。如果不指定此参数,可以通过设置环境变量SPGCLIENTENCODING达到相同的目的

-f file --file=file #输出到指定的文件中。如果没有指定此参数,则输出到标准输出中。

-F format或--format=format #选择输出的格式。format可以是p、c或t。
p是plain的意思,为纯文本SQL脚本文件的格式,还是默认值。大库不荐
c是custom的意思,以一个适合pg_restore使用的自定义二进制格式输出并归档。这是最灵活的输出格式,在该格式中允许手动查询并且可以在pg_restore恢复时重排归档项的顺序。该格式默认是压缩的。
t是tar的意思,以一个适合输入pg_restore的tar格式输出并归档。该输出格式允许手动选择并且在恢复时重排归档项的顺序,但是这个重排序是有限制的,比如,表数据项的相关顺序在恢复时不能更改。同时,tar格式不支持压缩,并且对独立表的大小限制为8GB。

-n schema或--schema=schema #只转储匹配 schema模式内容,包括模式本身以及其中包含的对象。如果没有声明这个选项,所有目标数据库中的非系统模式都会被转储出来。可以使用多个-n选项指定多个模式。
-t table或--table=table #只转储出匹配table的表、视图、序列。可以使用多个-t选项匹配多个表。同样table参数将按照psql的\d命令的规则被解释为匹配模式,因此可以使用通配符匹配多个模式。在使用通配符时,最好用引号进行界定,以防止shell将通配符进行扩展
-T table或--exclude-table=table #不转储任何匹配table模式的表。模式匹配规则与t完全相同。可以指定多个-T以排除多种匹配的表。如果同时指定了-t和-T,那么将只转储匹配-t但不匹配-T的表。如果出现了-T而未出现-t,那么匹配-T的表不会被转储。

使用pg_dump的自定义备份或tar类型的备份需要使用pg_restore工具来恢复。

pg_restore命令的格式如下:

pg_restore [connection-option...] [option...] [filename]

pg_restore 的连接参数与pg_dump基本相同,如下
-h host或--host=host
-p port或--port=port
-U username或--username=username -w或--no-password
-W或--password
-d dbname或--dbname=dbname #不同之处在于,pg_restore使用-d的参数来连接指定的数据库并恢复数据至此数据库
filename #要恢复的备份文件的位置。如果没有声明,则使用标准输入。
-a或--data-only #只恢复数据,而不恢复表模式(数据定义)
-c或--clean #创建数据库对象前先清理(删除)它们。
-C或--create #在恢复数据库之前先创建它。如果出现了这个选项,和-d在一起的数据库名只是用于发出最初的CREATE DATABASE命令,所有数据都恢复到名字出现在归档中的数据库中。
-F format 或--format=format #指定备份文件的格式。pg_restore可自动判断格式,如果一定要指定,它可以是t或c之一

t表示tar,指备份文件是一个tar文件
c表示custom,备份的格式是来自pg_dump的自定义格式,这是最灵活的格式,因为它允许对数据重新排序,也允许重载表模式元素,默认这个格式是压缩的。

-n namespace或--schema=schema #只恢复指定名字的模式里的定义和/或数据。这个选项可以和-t选项一起使用,只恢复一个表的数据。
-t table或--table=table #只恢复指定的表的定义和/或数据。可以与-n参数(指定schema)联合使用

范例:

#备份单个数据库test中的所有表的指定目录
pg_dump -U postgres -f /backup/test_backup test

#备份test数据库中的t1表和t2表:
pg_dump -U postgres -t t1 -t t2 -f /backup/test_backup_t1_t2 test

范例

#备份指定数据库
pg_dump -d testdb > /backup/testdb.sql

#恢复过程
#注意:事先需要存在数据库,且删除所有表后才能恢复
psql -d testdb < /backup/testdb.sql

范例:使用pg_dump备份所有的数据库,其操作和pg_dump类似

#备份全部数据库,每个数据库都需要输入密码,有N个数据库,则需要输入N次密码
pg_dumpall -U postgres -f full_backup.sql
pg_dumpall > full_backup.sql

#恢复
psql < full_backup.sql

范例:使用pg_dump和pg_restore备份还原

#当连接的是一个本地数据库,并不需要密码时,要对数据库hellodb进行备份,备份文件的格式是脚本文件格式

pg_dump -C hellodb > hellodb.sql
#使用pg_dump也可以备份一个远程的数据库,如下面的命令备份10.0.0.200机器上的hellodb数据库
pg_dump -h 10.0.0.200 -U postgres -C hellodb > hellodb.sql

#如果想生成的备份文件格式为自定义格式,可以使用下面的命令:
pg_dump -Fc -h 10.0.0.200 -Upostgres hellodb > hellodb.dump

#查看备份文件内容
pg_restore hellodb.dump

#查看备份的项目
pg_restore -l hellodb.dump

#把上述备份文件恢复到另一个数据库hellodb2中
#先创建数据库才能恢复
psql -U postgres -h 10.0.0.200 -c "create database hellodb2"
#还原
pg_restore -h 10.0.0.200 -U postgres -d hellodb2 hellodb.dump

#只备份数据库hellodb中的表students
pg_dump -h 10.0.0.200 -Upostgres -t students hellodb >students.sql

#备份schema1模式中所有以job开头的表,但是不包括job_log表
pg_dump -t 'schema1.job*' -T schema1.job_log hellodb > schema1.emp.sql

#备份所有数据库对象,但是不包括名字以_log结尾的表
pg_dump -T '*_log' hellodb > log.sql

#先从10.0.0.200备份数据库hellodb,然后恢复到10.0.0.100机器上。
pg_dump -h 10.0.0.200 -U postgres hellodb -Fc > hellodb.dump
pg_restore -h 10.0.0.100 -U postgres -C -d postgres hellodb.dump
#在pg_restore命令中,-d中指定的数据库可以是10.0.0.200机器上实例中的数据库,pg_restore仅用该数据库名称进行连接,-C表示先执行CREATE DATABASE命令创建hellodb数据库,然后在重新连接到hellodb数据库,最后把备份的表和其它对象建到hellodb数据库中。

#将备份出来的数据重新加载到一个新建的不同名称的数据库hellodb2中
createdb -T template0 hellodb2
pg_restore -d hellodb2 hellodb.dump
#注意,上面的命令从template0而不是template1创建新数据库,确保干净。这里没有使用-C选项,而是直接连接到要恢复的数据库上。

5.3.2 COPY命令实现备份还原

COPY命令支持在PostgreSQL表和文件之间交换数据。

COPY TO把一个表的所有内容都拷贝到一个文件,而COPY FROM从一个文件里拷贝数据到一个表里(把数据附加到表中已经存在的内容里)。COPY TO还能拷贝SELECT查询的结果。

如果声明了一个字段列表,COPY将只在文件和表之间拷贝已声明字段的数据。如果表中有任何不在字段列表里的字段,那么COPY FROM将为哪些字段插入缺省值。

带文件名的COPY指示PostgreSQL服务器直接从文件中读写数据。如果声明了文件名,那么服务器必须可以访问该文件,而且文件名必须从服务器的角度声明。如果使用了PROGRAM选项,则服务器会从指定的这个程序进行输入或是写入该程序作为输出。如果使用 了STDIN或STDOUT选项,那么数据将通过客户端和服务器之间的连接来传输。

命令:

#导入
COPY table_name [ ( column_name [, ...] ) ]
    FROM { 'filename' | PROGRAM 'command' | STDIN }
    [ [ WITH ] ( option [, ...] ) ]
    [ WHERE condition ]

#导出
COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
    TO { 'filename' | PROGRAM 'command' | STDOUT }
    [ [ WITH ] ( option [, ...] ) ]

#常用参数说明:
table_name 现存表的名字(可以有模式装饰)
column_name 可选的待拷贝字段列表。如果没有声明字段列表,那么将使用所有字段
query 一个必须用圆括弧包围的SELECT或VALUES命令,其结果将被拷贝
filename 输入或输出文件的路径名。输入文件名可以是绝对或是相对的路径,但输出文件名必须是绝对路径。Windows用户可能需要使用E字符串和双反斜线作为路径名称
PROGRAM 需执行的程序名。在COPY FROM命令中,输入是从程序的标准输出中读取,而在COPY TO中,命令的输出会作为程序的标准输入。
注意,程序一般是在命令行界面下执行,当用户需要传递一些变量给程序时,如果这些变量的来源不是可靠的,用户必须小心过滤处理哪些命令行界面来说是特殊意义的字符。基于安全的原因,最好是使用固定的命令字符串,或者至少是应避免直接使用用户输入(应先过滤特殊字符)
STDOUT 声明输入将写入客户端应用。
FORMAT 选择被读或者写的数据格式:text、csv(逗号分隔值),或者binary。默认是text

#注意:
copy命令必须在psql命令行执行,执行用户必须为superuser,否则会提示错误
如果用普通用户进行执行,需要在copy前面假如"\",即\copy即可。

范例:导出

#示例
COPY students TO '/tmp/students.csv' with csv;

#可以导出指定的属性
COPY students(stuid,name) TO '/tmp/students.csv' with csv;

#可以使用select语句:
COPY (select * from students) to '/tmp/students.csv' with csv;

#可以指定要导出哪些字段并带有列名:
COPY (select stuid,name,age from students) to '/tmp/students.csv' with csv header;

范例:导入

#导入命令基本与导出一样,只是将TO改为FROM
create table students2(like students);
COPY students2 FROM '/tmp/students.csv' with csv;

#如果导出的时候,指定了header属性,那么在导入的时候,也需要指定:
COPY students(stuid,name,age,gender) to '/tmp/students.csv' with csv header;
COPY students2(stuid,name,age,gender) FROM '/tmp/students.csv' with csv header;

5.3 物理备份

物理备份分为冷备份和热备份

  • 冷备份:最简单的物理备份就是冷备份,也就是把数据库停止,然后把数据库的PGDATA目录拷出来即可。

​ 由于POstgreSQL把与数据库实例有关的配置文件和数据文件都放在$PGDATA目录下,所以PostgreSQL做冷备份很简单

  • 热备份:不停止数据库的数据库备份,称之为热备份或在线备份。在PostgreSQL中通常的热备份方法有两种。
    • 第一种方法:使用数据库的PITR方法利用pg_basebackup工具进行热备份
    • 第二种方法:使用文件系统或块设备级别的快照功能完成备份。因为使用了快照,所以也能让备份出来的数据库与源数据库一致。

热备份流程:

  • 以数据库超级用户身份连接到数据库,发出命令:select pgstart_backup(‘label’);

    pg_start_backup()主要做了以下两个工作:

    • 设置写日志标志为:XLogCtl->Insert.forcePageWrites=true,也就是把这个标志设置为true后,数据库会把变化的整个数据块都记录到数据库中,而不仅仅是块中记录的变化。
    • 强制发生一次checkpoint点。
  • 执行备份。使用任何方便的文件系统工具比如tar,或直接把数据目录复制下来。这些操作过程中既不需要关闭数据库,也不需要停止数据库的任何操作。

  • 再次以数据库超级用户身份连接数据库,然后发出命令:select pg_stop_backup();

这将中止备份模式并自动切换到下一个WAL段。自动切换是为了让在备份间隔中写入的最后一个WAL段文件可以立即为下次备份做好准备。

  • 拷贝备份过程中产生的归档WAL日志文件

范例:冷备份还原

#备份
root@gf:~# pg_ctl stop
root@gf:~# mkdir /backup
root@gf:~# cp -a $PGDATA/ /backup/pgdata-`data +%F`
root@gf:~# pg_ctl start
#还原
root@gf:~# pg_ctl stop
root@gf:~# rm -rf $PGDATA/
root@gf:~# cp -a /backup/pgdata-2022-2-16/* $PGDATA/
root@gf:~# pg_ctl start

范例:热备份和还原

在这里插入图片描述

5.4 PITR(Point-in-Time Recovery)介绍

PostgreSQL支持类似于MySQL的主从复制的架构,一个Master服务器database同步数据到多个Standby Server

PostgreSQL的主从同步是基于WAL(write ahead log预写式日志)日志实现的。

PostgreSQL在数据目录的$PGDATA/pg_wal重做日志目录中始终维护着一个WAL日志文件。这个日志文件用于记录数据库数据文件的每次改变。当初设计这个日志文件的主要目的是为了在数据库异常崩溃后,能够通过重放最后一次checkpoint点之后的日志文件,把数据库推到一致状态。

事实上,这种日志文件机制,也提供了一种数据库热备份方案:在把数据库使用文件系统的方式备份出来的同时把相应的在线WAL日志也备份出来。虽然直接拷贝数据库数据文件会导致拷贝出来的文件不一致(比如拷贝的多个数据文件不是同一个时间点文件;拷贝一个8KB的数据块时,也存在不一致的情况:假设刚拷贝完前4KB的块,数据库又写了后4KB的块内容,那么所拷贝的块就不是一个完整的数据块),但因为有了WAL日志,即使备份出来的数据块不一致,也可以重放备份开始后的WAL日志,把备份的内容推到一致状态。

由此可见,有了WAL日志之后,备份数据库时不在需要完美的一致性备份了,备份中任何数据的非一致性都会被重放WAL日志文件进行纠正,所以在备份数据库时可以通过简单的cp命令或tar等拷贝、备份文件来实现数据库的在线备份。

不停地重放WAL日志就可以把数据推到备份结束后地任意一个时间点,这就是基于时间点的备份Point-in-Time Recovery,缩写为PITR。

使用简单的cp命令或其它命令把数据库给在线拷贝出来的备份,被称为基础备份。后续WAL日志的备份与此基础备份构成一个完整备份。把基础备份恢复到另一台主机,然后不停地从原始数据库机器上接收WAL日志,在新机器上持续重放WAL日志,这样就可以在任何时间内在另一台机器上打开新产生地数据库。它拥有当前数据最新的数据状态。此新主机上的数据库称为Standby数据库,当前的主数据库出现问题故障无法正常提供服务时,可以把Standby数据库打开提供服务,从而实现高可用。

把WAL日志传送到另一台机器上的方法有两种,一种是通过归档WAL日志实现,一种是被称为流复制的方法。

6 PostgreSQL高可用

6.1 流复制介绍

流复制streaming replication是实现PostgreSQL的高可用的常见技术。

PostgreSQL流复制相当于MySQL的主从复制,可以实现数据同步和数据备份

6.1.1 什么是流复制

PostgreSQL通过WAL日志来传送的方式有两种:基于文件的日志传送和流复制

不同于基于文件的日志传送,流复制的关键在于"流",所谓流就是没有界限的一串数据,类似于河里水流,是连成一片的。

流复制比使用基于文件方式的日志传送更能使一台后备服务器保持最新的状态。后备服务器连接到主服务器,主服务器则在WAL记录产生时即将他们以流式传送给后备服务器而不必等到WAL文件被填充。

比如有一个大文件要从本地主机发送到远程主机,如果是按照"流"接收到的话,我们可以一边接收,一边将文本流存入文件系统。这样,等到"流"接收完了,硬盘写入操作也已经完成。

6.1.2 流复制发展历史

PostgreSQL在流复制出现之前,使用的就是基于文件的日志传送:对WAL日志进行拷贝,因此从库始终落后主库一个日志文件,并且还需要使用rsync工具同步数据目录。

而流复制出现是从2010年推出的PostgreSQL9.0开始的,其历史大致为:

  • 起源:PostgreSQL9.0开始支持流式物理复制,用户可以通过流式复制,构建只读备库(主备物理复制,块级别一致)。流式物理复制可以做到极低的延迟(通常在1毫米以内)。
  • 同步流复制:PostgreSQL9.1开始支持同步复制,但是当时只支持一个同步流复制备节点(例如配置了3个备,只有一个同步模式的,其它都是异步模式)。同步流复制的出现,保证了数据的0丢失。
  • 级联流复制:PostgreSQL9.2支持级联流复制。即备库还可以再连备库。
  • 流式虚拟备库:PostgreSQL9.2还支持虚拟备库,即就是只有WAL,没有数据文件的备库。
  • 逻辑复制:PostgreSQL9.4开始可以实现逻辑复制,逻辑复制可以做到对主库的部分复制,例如表级复制,而不是整个集群的块级一致复制。
  • 增加多种同步级别:PostgreSQL9.6版本开始可以通过synchronous_commit参数,来配置事务的同步级别。

6.1.3 流复制原理

备库不断的从主库同步相应的数据,并再备库apply每个WAL record,这里的流复制每次传输单位是WAL日志的record。流复制的核心思想是主节点将所有写入操作记录到一个称为写入前日志(Write-Ahead Logging,WAL)的文件中,而从节点则从主节点的WAL中读取这些变更并将应用到自己的数据库中。以下是流复制的主要步骤和原理

  • WAL日志生成:
    • 当主节点上发生写入操作时,该操作将被记录到WAL中。WAL是一个顺序写入的日志文件,它记录了所有数据库变更的详细信息,包括事务ID、操作类型、受影响的数据等
  • WAL日志传输
    • 主节点通过WAL日志传输过程(walsender)将WAL日志块发送给从节点。从节点上的WAL日志接收进程(walreceiver)接收到这些WAL日志块后,会将其写入到本地的WAL日志文件中。
  • WAL日志应用
    • 从节点上的启动进行(startup)会不断地从本地WAL日志文件中读取变更记录,并将这些变更应用到自己地数据库中。应用过程是顺序执行的,以确保从节点上的数据与主节点保持一致。
  • 数据同步与一致性
    • 通过流复制,主节点和从节点之间可以保持数据的实时同步,确保数据的一致性。再同步复制模式下,主节点必须确保事务的变更已经被从节点接收并应用后,才会提交该事务,从而确保数据的一致性。

在这里插入图片描述

6.1.4 流复制按照同步方式分类

流复制类似于MySQL的同步机制,支持以下两桶同步机制

  • 异步流复制
  • 同步流复制

在实际生产环境中,建议需要根据环境的实际情况来选择同步或异步模式,同步模式需要等待备库的写盘才能返回成功,如此一来,再主备库复制正常的情况下,能够保证备库的不丢失,但是带来的负面问题,一旦备库宕机,主库就会挂起而无法进行正常操作,即再同步模式中,备库对主库的有很打的影响,而异步模式就不会。因此,再生产环境中,大多会选择异步复制模式,而非同步模式

6.1.5 流复制特点

  • 延迟极低,不怕大事务
  • 支持断点续传
  • 支持多副本
  • 配置简单
  • 备库与主库物理完全一致,并支持只读

6.2 实现流复制

6.2.1 基础环境准备

两个主机节点

172.16.10.20 Master
172.16.10.21 Standby

6.2.2 Master节点配置

#创建复制的用户并授权
postgres=# create role repluser with replication login password '123456';
CREATE ROLE
#修改pg_hba.conf进行授权
root@gf:/apps# cat /pgsql/data/pg_hba.conf
host    replication     repluser        172.16.10.0/24          md5

#修改配置(可选):
root@gf:/apps# cat /pgsql/data/postgresql.conf
synchronous_standby_names = '*' #开启此项,表示同步方式,需要同时打开synchronous_commit = on,此为默认值,默认是异步方式
synchronous_commit = on  #开启同步模式
archive_mode = on #建议打开归档模式,防止长时间无法同步,WAL被覆盖造成数据丢失
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'   
wal_level = replica #设置wal的级别
max_wal_senders = 5 #这个设置可以最多有几个流复制连接,一般有几个从节点就设置几个
wal_keep_segments = 128 #设置流复制保留的最多的WAL文件数目
wal_sender_timeout = 60s #设置流复制主机发送数据的超时时间
max_connections = 200 #一般查多于写的应用从库的最大连接数要比较大
hot_standby = on #对主库无影响。用于将来可能会成为从库,这台机器不仅仅是用于数据归档,也用于数据查询,在从库上配置此项后为只读
max_standby_streaming_delay = 30s #数据流备份的最大延迟时间
wal_receiver_status_interval = 10s #多久向主报告一次从的状态,当然从每次数据复制都会向主报告状态,只是设置最长的间隔时间
hot_standby_feedback = on #如果有错误的数据复制,是否向主进行反馈
wal_log_hints =on #对非关键更新进行整页写入

6.2.3 Standby节点配置

#清空数据和归档
root@gf:~# pg_ctl stop -D $PGDATA
root@gf:~# rm -rf /pgsql/data/*
root@gf:~# rm -rf /archive/*
root@gf:~# rm -rf /pgsql/backup/*

#备份主库数据到备库
pg_basebackup -D /pgsql/backup/ -Ft -Pv -Urepluser -h 172.16.10.20 -p 5432 -R

#还原备份的数据,实现初始的主从数据同步
root@gf:~# tar -xvf /pgsql/backup/base.tar -C /pgsql/data/
root@gf:~# tar -xvf /pgsql/backup/pg_wal.tar -C /archive/


#方法1
#修改postgresql.conf文件
#添加下面两行
primary_conninfo = 'host=172.16.10.20 port=5432 user=repluser password=123456'
restore_command = 'cp /archive/%f %p' #此项可不配置

#修改配置(可选):
hot_standby = on #开启此项,此是默认项
recovery_target_timeline = lastest #默认
max_connections = 120 #大于等于主节点,正式环境应当重新考虑此值的大小
max_standby_streaming_delay = 30s #数据流备份的最大延迟时间
wal_receiver_status_interval = 10s #多久向主报告一次从的状态,当然从每次数据复制都会向主报告状态,只是设置最长的间隔时间
hot_standby_feedback = on #如果有错误的数据复制,是否向主进行反馈
max_wal_senders = 15
logging_conllector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'

6.2.4 监控同步状态

6.2.4.1 在主库查看状态
root@gf:~# pg_controldata
pg_control version number:            1300
Catalog version number:               202107181
Database system identifier:           7458157620107561034
Database cluster state:               in production #主库状态

postgres=# select pid,state,client_addr,sync_priority,sync_state from pg_stat_replication;
 pid  |   state   | client_addr  | sync_priority | sync_state 
------+-----------+--------------+---------------+------------
 3792 | streaming | 172.16.10.21 |             0 | async


#下面只在主节点查看同步模式,注意:如果无从节点连接,将无任何显示信息
postgres=#  select pg_current_wal_insert_lsn(),* from pg_stat_replication;
-[ RECORD 1 ]-------------+------------------------------
pg_current_wal_insert_lsn | 0/3C07EAB8 #当前lsn号
pid                       | 3792
usesysid                  | 16551
usename                   | repluser
application_name          | walreceiver
client_addr               | 172.16.10.21
client_hostname           | 
client_port               | 50174
backend_start             | 2025-02-10 10:36:09.992306+08
backend_xmin              | 2684
state                     | streaming
sent_lsn                  | 0/3C07EAB8
write_lsn                 | 0/3C07EAB8 #同步的lsn号,和上面一致,说明同步,有差表示有同步延迟
flush_lsn                 | 0/3C07EAB8
replay_lsn                | 0/3C07EAB8
write_lag                 | 
flush_lag                 | 
replay_lag                | 
sync_priority             | 0
sync_state                | async #当前是异步,同步显示为sync
reply_time                | 2025-02-10 10:37:40.677288+08


#服务器查看数据库是否为备库,f表主库,t表示为备库
postgres=# select * from pg_is_in_recovery();
-[ RECORD 1 ]-----+--
pg_is_in_recovery | f


root@gf:~# ps -aux |grep walsender
postgres    3792  0.0  0.1 175248  7884 ?        Ss   10:36   0:00 postgres: walsender repluser 172.16.10.21(50174) streaming 0/3C07EAB8

6.2.4.2 在从库查看状态
#从节点可以读
sample_1=# select * from sample_table_activity;
 id |                     name                     
----+----------------------------------------------
 77 | c949ff0a-af8e-470f-b831-fd7332fdc856
 78 | 629f3b8c-7c66-455e-95a2-bb10b33531e7
 79 | 71793acb-ebf9-43c0-91c2-14155eef4df8
 80 | 7dd2efd6-e6b4-48fd-9100-3c6425ec275b
 76 | updated f0bea11f-7691-4bc8-aa6b-f52078a21168
(5 rows)

#从节点不支持写

sample_1=# delete from sample_table_activity where id=76;
2025-02-10 10:43:34.254 CST [2305] ERROR:  cannot execute DELETE in a read-only transaction
2025-02-10 10:43:34.254 CST [2305] STATEMENT:  delete from sample_table_activity where id=76;
ERROR:  cannot execute DELETE in a read-only transaction

postgres@gf:~$ pg_controldata 
pg_control version number:            1300
Catalog version number:               202107181
Database system identifier:           7458157620107561034
Database cluster state:               in archive recovery #备库状态

postgres=# select * from pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)

postgres=# select * from pg_stat_wal_receiver;
-[ RECORD 1 ]---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pid                   | 2291
status                | streaming
receive_start_lsn     | 0/3B000000
receive_start_tli     | 1
written_lsn           | 0/3C07EAB8
flushed_lsn           | 0/3C07EAB8
received_tli          | 1
last_msg_send_time    | 2025-02-10 10:45:10.589419+08
last_msg_receipt_time | 2025-02-10 10:45:10.592393+08
latest_end_lsn        | 0/3C07EAB8
latest_end_time       | 2025-02-10 10:36:09.993619+08
slot_name             | 
sender_host           | 172.16.10.20
sender_port           | 5432
conninfo              | user=repluser password=******** channel_binding=disable dbname=replication host=172.16.10.20 port=5432 fallback_application_name=walreceiver sslmode=disable sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any

#查看进程
postgres@gf:~$ ps -aux |grep postgres
root       2261  0.0  0.1  61756  3684 pts/0    S    02:35   0:00 su - postgres
postgres   2262  0.0  0.2  21464  5084 pts/0    S    02:35   0:00 -su
postgres   2279  0.0  0.8 174192 17560 ?        Ss   02:36   0:00 /apps/pgsql/bin/postgres
postgres   2283  0.0  0.4 174456  9308 ?        Ss   02:36   0:00 postgres: startup recovering 00000001000000000000003C
postgres   2288  0.0  0.2 174192  5248 ?        Ss   02:36   0:00 postgres: checkpointer 
postgres   2289  0.0  0.1 174192  2560 ?        Ss   02:36   0:00 postgres: background writer
postgres   2290  0.0  0.1  28968  2056 ?        Ss   02:36   0:00 postgres: stats collector
postgres   2291  0.0  0.2 179048  5956 ?        Ss   02:36   0:00 postgres: walreceiver streaming 0/3C07EAB8
postgres   2312  0.0  0.1  38380  3660 pts/0    R+   02:45   0:00 ps -aux
postgres   2313  0.0  0.0  13140  1072 pts/0    S+   02:45   0:00 grep --color=auto postgres

7 PostgreSQL Replication Slots介绍

PostgreSQL的复制槽(Replication Slots)主要用于物理复制数据的场景,可以视为数据库复制的一种中间件,用于在源节点和目标节点之间传输数据变动信息。其主要作用包括:

  1. 确保数据的完整性和一致性:复制槽能够确保下游节点保留所有需要的WAL(Write Ahead Log)文件,以便在发生故障时可以进行恢复。
  2. 作为中间件:在进行物理复制时,复制槽可以作为一个中间件,将逻辑数据变动信息从源节点传到目标节点

关于复制槽的使用场景,以下是一些关键点:

  • 流复制:在PostgreSQL的流复制机制中,复制槽起到了关键作用。通过创建和使用复制槽,可以确保主节点上的WAL文件被正确地保留并传输到备节点,从而实现数据地实时同步。
  • 结合Flink:虽然Flink本身并不直接使用PostgreSQL的复制槽功能,但在某些场景下,Flink可以与PostgreSQL的复制功能结合使用。例如,Flink CDC(Change Data Capture)功能可以基于PostgreSQL的逻辑复制功能来捕获数据变更,并将这些变更实时地传输到目标系统。在这个过程中,虽然Flink CDC直接连接到PostgreSQL的主库以获取数据变更,但PostgreSQL的复制槽功能仍然在主库上创建和管理逻辑复制槽,以确保数据的完整性和一致性。

复制槽的使用需要注意以下几点:

  • 非持久化:默认情况下,复制槽只在源数据库地当前会话中有效,关闭会话后将丢失。如果血药在数据库重启后任然保留复制槽,需要手动将其持久化
  • 唯一性:每个复制槽都必须具有唯一地名称,以便于管理和识别
  • 输出插件:复制槽必须与输出插件关联,以确定要将更改如何传播到目标数据库。常见地输出插件包括pgoutput、wal2json等。

总之,PostgreSQL的复制槽功能是实现物理复制的重要工具,能够确保数据的完整性和一致性,并提供高效的复制方式。在使用复制槽时,需要仔细评估和计划,并确保有足够的技术支持来应对可能出现的问题。

支持写

sample_1=# delete from sample_table_activity where id=76;
2025-02-10 10:43:34.254 CST [2305] ERROR: cannot execute DELETE in a read-only transaction
2025-02-10 10:43:34.254 CST [2305] STATEMENT: delete from sample_table_activity where id=76;
ERROR: cannot execute DELETE in a read-only transaction

postgres@gf:~$ pg_controldata
pg_control version number: 1300
Catalog version number: 202107181
Database system identifier: 7458157620107561034
Database cluster state: in archive recovery #备库状态

postgres=# select * from pg_is_in_recovery();
pg_is_in_recovery

t
(1 row)

postgres=# select * from pg_stat_wal_receiver;
-[ RECORD 1 ]---------±---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pid | 2291
status | streaming
receive_start_lsn | 0/3B000000
receive_start_tli | 1
written_lsn | 0/3C07EAB8
flushed_lsn | 0/3C07EAB8
received_tli | 1
last_msg_send_time | 2025-02-10 10:45:10.589419+08
last_msg_receipt_time | 2025-02-10 10:45:10.592393+08
latest_end_lsn | 0/3C07EAB8
latest_end_time | 2025-02-10 10:36:09.993619+08
slot_name |
sender_host | 172.16.10.20
sender_port | 5432
conninfo | user=repluser password=******** channel_binding=disable dbname=replication host=172.16.10.20 port=5432 fallback_application_name=walreceiver sslmode=disable sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any

#查看进程
postgres@gf:~$ ps -aux |grep postgres
root 2261 0.0 0.1 61756 3684 pts/0 S 02:35 0:00 su - postgres
postgres 2262 0.0 0.2 21464 5084 pts/0 S 02:35 0:00 -su
postgres 2279 0.0 0.8 174192 17560 ? Ss 02:36 0:00 /apps/pgsql/bin/postgres
postgres 2283 0.0 0.4 174456 9308 ? Ss 02:36 0:00 postgres: startup recovering 00000001000000000000003C
postgres 2288 0.0 0.2 174192 5248 ? Ss 02:36 0:00 postgres: checkpointer
postgres 2289 0.0 0.1 174192 2560 ? Ss 02:36 0:00 postgres: background writer
postgres 2290 0.0 0.1 28968 2056 ? Ss 02:36 0:00 postgres: stats collector
postgres 2291 0.0 0.2 179048 5956 ? Ss 02:36 0:00 postgres: walreceiver streaming 0/3C07EAB8
postgres 2312 0.0 0.1 38380 3660 pts/0 R+ 02:45 0:00 ps -aux
postgres 2313 0.0 0.0 13140 1072 pts/0 S+ 02:45 0:00 grep --color=auto postgres


# 7 PostgreSQL Replication Slots介绍

PostgreSQL的复制槽(Replication Slots)主要用于物理复制数据的场景,可以视为数据库复制的一种中间件,用于在源节点和目标节点之间传输数据变动信息。其主要作用包括:

1. **确保数据的完整性和一致性**:复制槽能够确保下游节点保留所有需要的WAL(Write Ahead Log)文件,以便在发生故障时可以进行恢复。
2. **作为中间件**:在进行物理复制时,复制槽可以作为一个中间件,将逻辑数据变动信息从源节点传到目标节点

关于复制槽的使用场景,以下是一些关键点:

- **流复制**:在PostgreSQL的流复制机制中,复制槽起到了关键作用。通过创建和使用复制槽,可以确保主节点上的WAL文件被正确地保留并传输到备节点,从而实现数据地实时同步。
- **结合Flink**:虽然Flink本身并不直接使用PostgreSQL的复制槽功能,但在某些场景下,Flink可以与PostgreSQL的复制功能结合使用。例如,Flink CDC(Change Data Capture)功能可以基于PostgreSQL的逻辑复制功能来捕获数据变更,并将这些变更实时地传输到目标系统。在这个过程中,虽然Flink CDC直接连接到PostgreSQL的主库以获取数据变更,但PostgreSQL的复制槽功能仍然在主库上创建和管理逻辑复制槽,以确保数据的完整性和一致性。
  ​

复制槽的使用需要注意以下几点:

- **非持久化**:默认情况下,复制槽只在源数据库地当前会话中有效,关闭会话后将丢失。如果血药在数据库重启后任然保留复制槽,需要手动将其持久化
- **唯一性**:每个复制槽都必须具有唯一地名称,以便于管理和识别
- **输出插件**:复制槽必须与输出插件关联,以确定要将更改如何传播到目标数据库。常见地输出插件包括pgoutput、wal2json等。

总之,PostgreSQL的复制槽功能是实现物理复制的重要工具,能够确保数据的完整性和一致性,并提供高效的复制方式。在使用复制槽时,需要仔细评估和计划,并确保有足够的技术支持来应对可能出现的问题。


相关文章:

  • GaussDB自带诊断工具实战指南
  • 青训营:简易分布式爬虫
  • 【Spring Boot 应用开发】-04-02 自动配置-数据源-手撸一个最简持久层工具类
  • 【CF记录】贪心——A. Scrambled Scrabble
  • 计算机毕业设计SpringBoot+Vue.js教师工作量管理系统(源码+文档+PPT+讲解)
  • PHP之变量
  • 前端模拟数据调试的方法
  • io学习----->文件io
  • 什么是索引下推?
  • 机器视觉开发教程——封装Halcon通用模板匹配工具【含免费教程源码】
  • java 查找两个集合的交集部分数据
  • K8s 1.27.1 实战系列(一)准备工作
  • 【零基础到精通Java合集】第二十九集:SQL常用优化手段
  • 双链路提升网络传输的可靠性扩展可用带宽
  • 【Oracle学习笔记】1.数据库组成对象
  • 前端开发10大框架深度解析
  • 前端基础之组件
  • CentOS 7 安装 Redis6.2.6
  • Docker的常用镜像
  • Linxu几种登陆方式介绍
  • 咸宁市委常委、市纪委书记官书云调任湖北省司法厅副厅长
  • 金融监管总局:近五年民企贷款投放年平均增速比各项贷款平均增速高出1.1个百分点
  • 美联储宣布维持基准利率不变
  • 湖北奥莱斯轮胎公司逃避监管排放大气污染物被罚25万元
  • 涉个人信息收集使用问题,15款App和16款SDK被通报
  • 五一假期上海边检查验出入境人员超61万人次,同比增长23%