文章目录
- 1.初始化数据库集群
- 2.PG参数介绍、优化
- 3.数据库防火墙介绍与配置
- 4.数据库物理架构
- 5.数据库逻辑架构
- 6.数据库权限体系
- 7.连接数据库
- 8.SSL链路
1.初始化数据库集群
使用PG的bki脚本创建元数据
[postgres@node4 postgresql]$ ll|grep postgres.bki
-rw-r--r--. 1 postgres postgres 810K Dec 28 15:33 postgres.bki
[postgres@node4 postgresql]$ pwd
/home/wangji/pginstall/share/postgresql
规划数据目录
- datafile($PGDATA)
- 默认的表空间是pg_default,其目录在$PG_DATA中,就是base目录,base就是一个默认的表空间
postgres=# \db
List of tablespaces
Name | Owner | Location
------------+----------+----------
pg_default | postgres |
pg_global | postgres |
$PGDATA下实际有很多文件
[postgres@node4 data]$ ll
total 68K
drwx------. 5 postgres postgres 41 Dec 28 15:39 base
-rw-------. 1 postgres postgres 44 Dec 28 15:39 current_logfiles
drwx------. 2 postgres postgres 4.0K Dec 28 15:42 global
drwx------. 2 postgres postgres 86 Dec 28 15:39 log
drwx------. 2 postgres postgres 6 Dec 28 15:39 pg_commit_ts
drwx------. 2 postgres postgres 6 Dec 28 15:39 pg_dynshmem
-rw-------. 1 postgres postgres 4.7K Dec 28 15:39 pg_hba.conf
-rw-------. 1 postgres postgres 1.6K Dec 28 15:39 pg_ident.conf
- 一张表的路径在什么地方??
\dt
postgres=# \df *.*file*
pg_catalog | pg_relation_filepath | text | regclass
依据结果创建表
select * into table new_tbl from pg_class;
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+---------+-------+----------
public | new_tbl | table | postgres
(1 row)
postgres=# select pg_relation_filepath('new_tbl');
pg_relation_filepath
----------------------
base/13580/17056
(1 row)
看下a表在哪?
表new_tbl对应的文件是base/13285/1915066;
base代表默认的表空间,一个表空间里有所有的数据库;
13285表示当前连接的是postgress数据库,其obj id=13285;
所以表postgres在postgress数据库中的位置是:表空间目录/数据库目录/数据库里面的表文件
- PG中一个instance可以创建多个database,当前的postgres中有3个数据库
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+---------+------------+-----------------------
postgres | postgres | UTF8 | C | en_US.utf8 |
template0 | postgres | UTF8 | C | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | C | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 rows)
规划表空间
- 在PG里,每一个表空间对应一个目录
- 数据表空间:由顺序IO、随机IO的IOPS决定
- 索引表空间,数据表空间的热数据放在SSD
规划REDO目录
- (1)磁盘能力:
pg的redo叫pg_wal预写式日志
REDO作用:保证数据一致性、持久化,REDO本身是顺序写IO,一个事务在提交时,只要保证其REDO持久化了,则可以认为该事务可以提交了,每一条REDO都有一条LSN,回滚时顺序回滚。
REDO功能:在线备份,时间点恢复,归档、容灾。
walwriter调用fsync把wal buffer中日志顺序刷到磁盘中
[postgres@node4 base]$ ps -ef|grep wal
postgres 3509006 3508921 0 15:39 ? 00:00:01 postgres: walwriter
- pg_test_fsync
测试fsyc命令,测试当前$PGDATA目录,每秒操作的同步写,单个REDO的page是8K
[postgres@node4 base]$ pg_test_fsync
- REDO建议使用SSD盘,若是机械盘,把异步打开,则事务调用异步write的接口就可以提交了,但是在OS crash时,可能会丢到10ms的数据
postgres=# show synchronous_commit ;
synchronous_commit
--------------------
off
(1 row)
postgres=# show wal_writer_delay ;
wal_writer_delay
------------------
10ms
(1 row)
- (2)REDO目录大小设置:
动态调度checkpoint写检查点,最长的检查点运行动态调度,在产生32G的REDO的周期内做checkpoint;
所以下面的值设置越大,REDO目录大小可能就越大
postgres=# show max_wal_size ;
max_wal_size
--------------
256GB
(1 row)
postgres=# show min_wal_size ;
min_wal_size
--------------
64GB
(1 row)
规划日志目录
- $PGDATA/log
规划临时对象表空间目录
- 临时对象默认写在当前数据库的默认表空间pg_default
- 临时表、索引、排序文件等:temp_tablespaces
- 所有的表的元数据,以及临时表的元数据放在global表空间,而临时表可以放在tempfs或者上述$PGDATA/base/psql_tmp等位置
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+---------+------------+-----------------------
postgres | postgres | UTF8 | C | en_US.utf8 |
postgres=# \l+
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
-----------+----------+----------+---------+------------+-----------------------+---------+------------+--------------------------------------------
postgres | postgres | UTF8 | C | en_US.utf8 | | 8653 kB | pg_default | default administrative connection database
规划归档目录
- 当一个REDO文件写满之后,eg16M,写满后拷贝至后面的目录
postgres=# show archive_command ;
规划备份目录
- initdb
- 该数据库实例的目录,该数据库文件都在这个目录
initdb参数中的DATADIR对应的是$PGDATA(/home/wangji/pginstall/data)
postgres=# show port;
port
------
1921
(1 row)
- 模板库的编码Encoding,本土化设置Collate
initdb --lc-ctype选项:若不会出现中文,仅有单字节字符,则设置为c
postgres=# \l+
List of databases
Name | Owner | Encoding | Collate | Ctype (--lc-ctype) | Access privileges | Size | Tablespace | Description
-----------+----------+----------+---------+------------+-----------------------+---------+------------+--------------------------------------------
postgres | postgres | UTF8 | C | en_US.utf8 | | 8653 kB | pg_default | default administrative connection database
- pg_trgm插件可以做中文查询,可以做中文模糊查询,可以建中文的倒排索引
postgres=# create extension pg_trgm;
CREATE EXTENSION
postgres=# \dx;
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+-----------------------------------------------------------------------------------------------
pg_trgm | 1.5 | public | text similarity measurement and index searching based on trigrams
- 测试db1和db2的Ctype区别,是否能够拆分中文字符(若Ctype是en_US.utf8是可以拆分字符的)
[postgres@node4 data]$ createdb "db2" --lc-ctype="C" -T template0
postgres=# \l+
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
-----------+----------+----------+---------+------------+-----------------------+---------+------------+--------------------------------------------
db1 | postgres | UTF8 | C | en_US.utf8 | | 7737 kB | pg_default |
db2 | postgres | UTF8 | C | C | | 7737 kB | pg_default |
db2=# \c db1;
db1=# create extension pg_trgm;
CREATE EXTENSION
db1=# \df *.*trgm*;
db1=# select show_trgm('你好王继');
show_trgm
-------------------------------------------
{0xea18f3,0xea6864,0xf98da8,0x3c980f,IgR}
(1 row)
拆分规则:在字符串前加2个空格,末尾加1个空格,然后每三个连续的字符作为一个最小的单元进行切词
db1=# \c db2;
db2=# select show_trgm('你好王继');
show_trgm
-----------
{}
(1 row)
- 在表中检索数组text[]里面的内容且要做模糊查询
里面的索引使用了gin倒排索引
表的大小
db1=# \dt+
List of relations
Schema | Name | Type | Owner | Persistence | Size | Description
--------+---------+-------+----------+-------------+------------+-------------
public | test_cn | table | postgres | permanent | 8192 bytes |
搜索时间
db1=# \timing
Timing is on.
db1=# \timing
Timing is off.
- initdb --data-checksums
这里是数据文件的PAGE数据库设置 - initdb --wal-segsize表示redo文件的大小,一般设置为16M
- 其他参数
wal8000是redo的目录
-k表示要做checksum,超级用户是postgres
-X指定redo的的目录
mkdir -p /home/wangji/pginstall_8000
chown -R postgres:postgres /home/wangji
export PGDATA=/home/wangji/pginstall_8000
mkdir -p /home/wangji/pginstall_8000_wal
chown -R postgres:postgres /home/wangji/pginstall_8000_wal
inttdb -D $PGDATA -U postgres -E UTF8 --lc-collate=C --lc-ctype=en_US.UTF8 -X /home/wangji/pginstall_8000_wal -k
- \du+
list roles
db1=# \du+;
List of roles
Role name | Attributes | Member of | Description
-----------+------------------------------------------------------------+-----------+-------------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {} |
可以发现postgres的密码是空的,但是这不意味着可以无密码登录,这取决于PG的ACL(pg_hba.conf)
db1=# select * from pg_authid ;
oid | rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolval
iduntil
------+---------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+-------
--------
10 | postgres | t | t | t | t | t | t | t | -1 | |
pgctl命令
- -o连接多个参数
- -c表示你设置的配置
若设置了环境变量,则直接执行pg_ctl start
启动
pg_ctl start -D $PGDATA -o "-c work_mem='3MB'" -o "-c xxx='xx'" ...
关闭
immediate不会做检查点,重启PG会做恢复
pg_ctl stop -m fast -D $PGDATA
pg_ctl stop -m immediate -D $PGDATA
进入单用户模式
- 什么时候要单用户?PostgreSQL single-user mode 单用户模式修复 database is not accepting commands to avoid wraparound data loss in database “…” 问题 - usage,like Repair Database vacuum freeze的目的是:修复数据库重使用xid的问题
top -c -u postgres可以看到单用户执行
[postgres@node4 pg_wal]$ postgres --single
PostgreSQL stand-alone backend 13.5
backend>
自启动
chmod +x /etc/rc.d/rc.local
vim /etc/rc.local
if [ -f /sys/kernel/mm/transparent_hugepage/enabled ];then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
su - postgres -c "pg_ctl start"
postgres环境变量配置
cat ~/.bash_profile
[ -f /var/lib/psql/.pgsql_profile ] && source /var/lib/psql/.pgsql_profile
2.PG参数介绍、优化
PostgreSQL 11 postgresql.conf ,位置$PGDATA,链接
- postgresql.conf与postgresql.auto.conf区别,会先读前者再读后者,若参数重复,则以后者为主
- pg支持动态修改参数,动态修改的参数会修改到postgresql.auto.conf;
参数优先级
postgres=# \h alter system
postgres=# alter system set work_mem ='4MB';
- eg:postgresql.auto.conf增加重复配置
[postgres@node4 data]$ tail postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
work_mem = '4MB'
work_mem = '6MB'
postgres=# show work_mem ;
work_mem
----------
6MB
(1 row)
数据库和用户级别的配置
此外,PG中可以在数据库启动后alter配置,postgresql.auto.conf,postgresql.conf配置参数,还可以配置数据库的(粒度更细,优先级更高),还可有配置user的
上面work_mem-4MB是角色的,下面work_mem-6MB是数据库的
postgres=# select * from pg_db_role_setting ;
setdatabase | setrole | setconfig
-------------+---------+-----------
0 0 work_mem-4MB
13285 0 work_mem-4MB
(0 rows)
将数据库的参数进行重置
postgres=# alter database postgres reset all;
ALTER DATABASE
postgres=# alter role all reset all;
ALTER ROLE
- 创建数据库,角色时可以限制连接数
postgres=# \h create database
postgres=# \h create role
- password_encryption用户密码md5策略
用户密码使用的是md5,md5就是密码+用户,两个连起来
postgres=# create user wangji password 'XXX@uss100';
postgres=# alter role wangji encrypted password '123';
postgres=# select * from pg_authid ;
|
17311 | wangji | f | t | f | f | t | f | f | -1 | md51486a17cc8f73ad6
fe6df5c209423493 |
postgres=# select md5('123wangji');
md5
----------------------------------
1486a17cc8f73ad6fe6df5c20942349
3.数据库防火墙介绍与配置
(1)OS的iptables
(2)见链接中的pg_hba.conf
4.数据库物理架构
postmaster
- 所有数据库进程的主进程
- 负责佳宁和fork子进程
- 监控子进程的状态,若子进程crash,则重启
starup
- 数据库恢复的进程
- eg:standby数据库通过流复制去获取主数据库的redo做回放,starup进程是standby用来回放redo的
syslogger
- 记录系统日志
pgstat
- 收集统计信息
- eg:计数器:insert多少记录
pgarch
- 若开启了归档,则postmaster会fork一个归档进程
- eg:REDO完毕之后,会进行归档
checkpoint
- 负责检查点的进程
- eg:将shared buffer中的脏页刷到盘里面。是直接持久化进行落盘的
bgwriter
- 负责把shared buffer中的脏数据用write写入磁盘
- eg:异步刷脏页,调用write说明并不是把脏页立即刷到磁盘中,而是可能写到OS cache,OS的bgwriter再将数据刷到磁盘
实际操作块设备的IO:checkpoint、redo、
autovacuum lanucher
- 负责检测回收垃圾数据的进程,若开启了autovacuum的话,那么postmaster会fork这个进程
autovacuum worker
- 真正负责回收垃圾数据的worker进程,是lanucher进程dork出来的
bgworker
- 分为很多种worker,eg:logic replication worker launcher流复制、parallel worker并行计算、replication worker等
wal sender
- 逻辑复制、流式物理复制的WAL发送进程
wal receiver
- 逻辑复制、流式物理复制的WAL接收进程
work process
- 工作进程,动态fork,eg:并行计算的进程
数据库进程结构
- 有10个连接,就有10个backend process相互交互
- 当bgwriter和checkpoint很忙的时候,backend process也会操作shared buffer,导致查询延迟增高,所以bgwriter的顺面周期设置小一点,干活周期设置长一点;backend process与WAL writer也有这样的类似关系;
- 当一个查询是可以是并行执行的请求时,会fork一堆的parallel workrs去执行
- 流复制:从节点fork一个wal receiver进程从主节点fork的wal sender进程获取redo日志
QUERY查询处理流程
- 链接
- 一个SQL主要流程如下:
(1)一个query进来时首先进行parse
(2)接着分辨是普通的query还是一个utility command(DDL、DCL)?
(3)OLTP为什么需要prepared statement?既支持简单,也支持复杂查询
若有几十万次请求,即几十万次SQL,性能会很差。所以有prepared statement。
原理:经过绿色框中五次,会产生一个通用的执行计划,并计算出一个平均成本,等下一次查询计划过来,会直接使用通用计划计算成本,与存在数据库中的平均成本相比较,差在10%内,则直接执行通用的执行计划,则不会执行rewrite和generate plans等动作。
5.数据库逻辑架构
- 链接
逻辑结构
- 一个实例,就是一个PG集群
- 一个数据库与一个数据库之间是隔离的,除非使用外部表等方式去互相访问
- schema就是namespace
- 不同的db和不同的schema都可以实现隔离,schedma权限给了用户a,没给b,他可以看到和访问里面的表,而b只能看到这些表,却不能访问
6.数据库权限体系
- 链接
komablog=# \h grant
Command: GRANT
Description: define access privileges
Syntax:
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
数据库客户端驱动
- 客户端连接数据库
- 链接
以root用户启动pg
手动创建root role,我这里是使用用户名为postgres来启动postgresql服务的
su postgres
# 创建root用户
postgres=#create user root with password 'password';
CREATE ROLE
# 将数据库权限赋予root用户
postgres=# GRANT ALL PRIVILEGES ON DATABASE mydatabase to root;
GRANT
# 将用户修改为超级用户(看实际需求)
postgres=# ALTER ROLE root WITH SUPERUSER;
postgres=# \q
也可以直接将root创建为超级用户,login是指允许登录
CREATE ROLE root superuser PASSWORD 'password' login;
7.连接数据库
cli
- psql
TAB 自动补齐COMMAND
komablog=# \?
General
\copyright show PostgreSQL usage and distribution terms
\crosstabview [COLUMNS] execute query and display results in crosstab
\errverbose show most recent error message at maximum
komablog=# \h cluster
Command: CLUSTER
Description: cluster a table according to an index
当前有多少数据库
komablog=# \l
有多少表空间
komablog=# \db
List of tablespaces
Name | Owner | Location
------------+----------+----------
pg_default | postgres |
pg_global | postgres |
多少表
komablog=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | test | table | postgres
public | twitters | table | postgres
public | users | table | postgres
列出所有表
komablog=# \dt *.*
List of relations
Schema | Name | Type | Owner
--------------------+-------------------------+-------+----------
information_schema | sql_features | table | postgres
GUI
- pgadmin
- navicat
使用流复制协议连接数据库
- 链接
psql "replication=1" -h host -p port -U user dbname
pg_basebackup,使用流协议备份
pg_receivewal,使用流协议实施归档
pg_recvlogical,使用流协议实时订阅
->psql "replication-1"
使用物理流复制协议去执行
komablog=#IDENTIFY_SYSTEM
8.SSL链路
客户端与服务器端的链路使用ssl加密
- 链接:PostgreSQL 如何实现网络压缩传输或加密传输(openssl)
- 操作
编译PG
--with-openssl
生成cert、key对
openssl
postgresql.conf
ssl = on # (change requires restart)
ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers
# (change requires restart)
ssl_renegotiation_limit = 512MB # amount of data between renegotiations
ssl_cert_file = 'server.crt' # (change requires restart)
ssl_key_file = 'server.key'
pg_hba.conf
#host DATABASE USER ADDRESS METHOD [OPTIONS]
#hostssl DATABASE USER ADDRESS METHOD [OPTIONS]
#hostnossl DATABASE USER ADDRESS METHOD [OPTIONS]
client
强制使用或不使用ssl的方法
psql "sslmode=require"
psql "sslmode=disable"
检验是否使用ssl连接
komablog=#create extension sslinfo;
komablog=#select ssl_cipher();
komablog=#select ssl_version();