5、服务控制

PostgreSQL的服务控制主要包括以下3类:

  1. 服务端的启动(start)、停止(stop)、重启(restart)、重载(reload)。
  2. 服务端的会话连接管理
  3. 服务端的实例管理

服务端的启动(start)、停止(stop)、重启(restart)、重载(reload)

在不同的平台上使用的命令稍有区别

  • 在RHEL/CentOS 平台上,有两种方式来管理,分别是PostgreSQL自带的管理命令pg_ctl和系统自带工具systemctl,命令用法如下:
#pg_ctl的命令用法:
pg_ctl start   [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o "OPTIONS"]
pg_ctl stop    [-W] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]
pg_ctl restart [-w] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]
               [-o "OPTIONS"]
pg_ctl reload  [-D DATADIR] [-s]
选项解释:
-D/--pgdata=DATADIR  设置启动的postgres进程的数据存储目录,如果不带这个参数,先查找PGDATA变量,没有这个变量,则默认为/var/lib/pgsql/9.6/data/目录。
-s  silent    安静模式,带上这个选项时,程序只会输出错误信息,不会输出其他信息
-t  --timeout=SECS  等待的时间,和-w一起合用
-w  在操作完成之前,一直等待
-W  不等到操作完成
-l --log=FILENAME  启动时,将日志记录到哪个文件,PostgreSQL默认的日志文件是记录在data目录下的pg_log目录中。
-m  --mode=MODE,表示执行这个操作时使用的模式,可以是smart、fast或immediate。

这个命令默认在postgres用户身份下才能执行,PostgreSQL自带的管理命令都在/usr/pgsql-9.6/bin目录下。因此执行这个命令需要使用绝对路径,或者将这个目录添加到系统路径。示例如下:

启动
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl start 
server starting
-bash-4.2$ < 2017-11-23 14:51:05.274 CST > LOG:  redirecting log output to logging collector process
< 2017-11-23 14:51:05.274 CST > HINT:  Future log output will appear in directory "pg_log".

不带任何参数时,默认将日志输出到shell界面。

-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl start -l /var/lib/pgsql/9.6/data/pg_log/postgresql.log
server starting

带日志记录消息时,只会返回一个服务器启动的消息。

停止
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl stop -m smart
waiting for server to shut down.... done
server stopped
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl start -l /var/lib/pgsql/9.6/data/pg_log/postgresql.log
server starting
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl stop -m fast
waiting for server to shut down.... done
server stopped
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl start -l /var/lib/pgsql/9.6/data/pg_log/postgresql.log
server starting
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl stop -m immediate
waiting for server to shut down.... done
server stopped

停止命令后面可以带3个参数,如上面代码所示,带的三个参数结束进程时,返回的信息都是一样的,那停止运行的三种模式区别在于什么呢?区别是:

  • smart:智能停止模式,根据服务端正在进行的工作来判断,比较忙碌时,等业务结束连接断开时停止。
  • fast:快速模式,即迅速断开所有连接,结束所有用户的事务,然后停止服务。
  • immediate:立即结束服务进程。
重启

restart命令后面的模式和stop命令的模式一致,相关控制也是一致的。restart里面包含stop和start两步。但是先停止服务再重启服务,在停止服务之前,数据库会将缓存中的数据写入到数据文件中,这在数据库操作中称为CHECKPOINT,这个动作花费的时间越长,重启时花费的时间就越短。同时这个动作中做的事情越多,则花费的时间越多。因此在重启数据库之前手动执行一次CHECKPOINT,可以让重启的时间更短,命令如下:
psql -c 'CHECKPOINT';
但是重启以后,因为数据库缓存被清空,需要通过数据库自带的数据文件来重建缓存,在大型数据库中,这样的操作非常耗时。因此预热缓存需要很长的时间,这中间的取舍就要根据业务需要来进行均衡操作(自己的想法)。

重载

重载一般用于修改配置文件后重新加载配置时使用,命令执行过程如下:

-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl  reload
server signaled

也是只给出一个信号。

上面还说到,可以使用系统自带的systemctl工具来管理服务。用法如下:

[root@cephadmin ~]# systemctl start postgresql-9.6
[root@cephadmin ~]# ps aux | grep postgres 
root      94651  0.0  0.3 212040  3196 pts/2    S    15:23   0:00 su - postgres
postgres  94652  0.6  0.3 116424  3124 pts/2    S+   15:23   0:00 -bash
postgres  94773  1.5  1.5 357552 15236 ?        Ss   15:23   0:00 /usr/pgsql-9.6/bin/postmaster -D /var/lib/pgsql/9.6/data/
postgres  94776  0.2  0.1 212556  1568 ?        Ss   15:23   0:00 postgres: logger process   
postgres  94778  0.0  0.1 357552  1684 ?        Ss   15:23   0:00 postgres: checkpointer process   
postgres  94779  0.0  0.1 357552  1920 ?        Ss   15:23   0:00 postgres: writer process   
postgres  94780  0.2  0.1 357552  1684 ?        Ss   15:23   0:00 postgres: wal writer process   
postgres  94781  0.0  0.2 357976  2756 ?        Ss   15:23   0:00 postgres: autovacuum launcher process   
postgres  94782  0.0  0.1 212552  1896 ?        Ss   15:23   0:00 postgres: stats collector process   
root      94819  0.0  0.0 112644   952 pts/0    R+   15:23   0:00 grep --color=auto postgres
[root@cephadmin ~]# systemctl stop postgresql-9.6
[root@cephadmin ~]# systemctl reload postgresql-9.6
Job for postgresql-9.6.service invalid.
[root@cephadmin ~]# systemctl start postgresql-9.6
[root@cephadmin ~]# systemctl restart postgresql-9.6

命令执行成功时,不会有任何提示,基本上都是要到日志里去查看。reload和restart选项必须在postgres进程已经在运行时才能使用,否则会有一个提示出错信息。

这里有一个地方需要注意,那就是使用pg_ctl命令启动的postgres进程和systemctl启动的postgres进程时不同的,在上面的代码中,我们看到postgres的启动命令是:
/usr/pgsql-9.6/bin/postmaster -D /var/lib/pgsql/9.6/data/
我们将这个进程结束,然后使用pg_ctl启动进程再看一下:

[root@cephadmin ~]# systemctl stop postgresql-9.6
[root@cephadmin ~]# su - postgres
Last login: Thu Nov 23 15:23:13 CST 2017 on pts/2
-bash-4.2$ /usr/pgsql-9.6/bin/pg_ctl start -l /var/lib/pgsql/9.6/data/pg_log/postgresql.log 
server starting
-bash-4.2$ ps aux | grep postgres
root      94651  0.0  0.3 212040  3196 pts/2    S    15:23   0:00 su - postgres
postgres  94652  0.0  0.3 116424  3124 pts/2    S+   15:23   0:00 -bash
root      95166  0.0  0.3 212040  3196 pts/0    S    15:28   0:00 su - postgres
postgres  95167  0.9  0.3 116552  3336 pts/0    S    15:28   0:00 -bash
postgres  95262  0.6  1.5 357552 15240 pts/0    S    15:29   0:00 /usr/pgsql-9.6/bin/postgres
postgres  95263  0.0  0.1 212556  1560 ?        Ss   15:29   0:00 postgres: logger process   
postgres  95265  0.0  0.1 357552  1676 ?        Ss   15:29   0:00 postgres: checkpointer process  
postgres  95266  0.0  0.1 357552  1916 ?        Ss   15:29   0:00 postgres: writer process   
postgres  95267  0.0  0.1 357552  1676 ?        Ss   15:29   0:00 postgres: wal writer process  
postgres  95268  0.0  0.2 357976  2752 ?        Ss   15:29   0:00 postgres: autovacuum launcher process  
postgres  95269  0.0  0.1 212552  1900 ?        Ss   15:29   0:00 postgres: stats collector process  
postgres  95270  0.0  0.1 139492  1628 pts/0    R+   15:29   0:00 ps aux
postgres  95271  0.0  0.0 112648   952 pts/0    R+   15:29   0:00 grep --color=auto postgres

从上面的显示信息里可以看到,启动postgres进程的命令是:
/usr/pgsql-9.6/bin/postgres
因此,当你使用pg_ctl命令启动postgres进程时,无法使用systemctl命令来停止。但是,使用systemctl启动的postgres进程,可以使用pg_ctl命令来结束。应该是在PostgreSQL的命令体系里,pg_ctl命令的权限更高。

服务端的会话连接管理

阻止新的连接

某些紧急情况下,需要完全锁定数据库,或者禁止用户访问数据库,阻止数据库连接的几种方式:

  • 暂停/恢复连接池
  • 停止服务(快速停止或紧急关闭进程,immediate级别,一般不推荐)
  • 设置数据库允许的连接数为0:ALTER DATABASE dbname CONNECTION LIMIT 0; 此命令会限制普通用户连接,但是超级用户还是可以连接;如下所示:
[root@cephadmin ~]# psql -U postgres
Password for user postgres: 
psql (9.6.6)
Type "help" for help.
postgres=# CREATE USER dbuser WITH PASSWORD 'dbuser1234';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE postgres to dbuser;
GRANT
postgres=# exit
postgres-# \q
[root@cephadmin ~]# psql -U dbuser -d postgres
Password for user dbuser: 
psql: FATAL:  too many connections for database "postgres"
[root@cephadmin ~]# psql -U postgres
Password for user postgres: 
psql (9.6.6)
Type "help" for help.

postgres=# 

在上面的示例中,首先创建一个普通用户dbuser,然后将postgres数据库的所有权限赋予给这个用户,最后尝试用这个用户登录。可以看到提示连接过多。但是再用postgres用户登录时,发现可以正常登录。

限制用户连接数

  • 限制每个用户允许的连接数为0:ALTER USER username CONNECTION LIMIT 0;也是限制普通用户,超级用户postgres不受限制。示例如下:
postgres=# ALTER DATABASE postgres CONNECTION LIMIT -1;
ALTER DATABASE
postgres=# \q
^[[A[root@cephadmin ~]# psql -U dbuser -d postgres  
Password for user dbuser: 
psql (9.6.6)
Type "help" for help. 

postgres=> \q
[root@cephadmin ~]# psql -U postgres
Password for user postgres: 
psql (9.6.6)
Type "help" for help.

postgres=# ALTER USER dbuser CONNECTION LIMIT 0;
ALTER ROLE
postgres=# \q
[root@cephadmin ~]# psql -U dbuser -d postgres
Password for user dbuser: 
psql: FATAL:  too many connections for role "dbuser"

在上面的示例中,我们先将数据库的连接设置为-1,表示允许连接。然后使用dbuser登录,看到可以正常登录,然后使用postgres登录,修改配置,将dbuser的连接数设置为0,再尝试用dbuser登录,提示连接过多。

  • 修改连接配置文件pg_hba.conf来限制所有的连接,然后重载文件,配置文件的配置如下:
#TYPE       DATABASE        USER        CIDR-ADDRESS        METHOD
local           all             all                         reject
host            all             all         0.0.0.0/0       reject

如果允许postgres可以登陆,则可以在将下面这一行添加为第一行:

local           all             postgres          peer

这运行postgres通过本地地址的socket连接(localhost)登陆。

  • 限制每个用户只允许一个会话:ALTER ROLE fred CONNECTION LIMIT 1;
    可以将值设为-1解除限制,改变了配置以后,已经建立的会话不受影响,但是重新连接的时候会提示连接受限。查看角色允许的连接数SQL语句如下:
    SELECT roleconnlimit FROM pg_roles WHERE rolename='fred';
    此时可以查看此角色已经建立的连接数,SQL语句如下:
    SELECT COUNT(*) FROM pg_stat_activity WHERE usename= 'fred';
    如果连接数超过限定的连接数,继续看下节的内容。
断开用户的连接

可以使用postgresql自带的函数pg_terminate_backend()来断开用户的连接,这个函数需要连接的pid作为参数。而pid可以从pg_stat_activity表中获得,筛选条件则有多种:

  • WHERE application_name = 'myappname'; #根据连接的应用名来筛选
postgres=# select pid from pg_stat_activity where application_name='psql';
  pid  
-------
 96661
(1 row)
  • WHERE waiting='t' #等待连接的会话,t表示true,即这个查询正处于等待状态。这个条件适用于PostgreSQL9.5及以下版本,在9.6版本中,这个字段被变更,不再适用。

  • WHERE state = '<IDLE> in transaction' #正在处理事务的会话

  • WHERE state = '<IDLE>' #处于空闲状态的会话

用来断开用户连接的SQL语句用法:

  • SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE ....
  • SELECT count(pg_terminate_backend(pid)) FROM pg_stat_activity WHERE usename NOT IN ( SELECT usename FROM pg_user WHERE usesuper);

第一个是根据筛选条件得到会话进程的PID,然后结束该进程。第二个是更安全的做法,避免断开自己的连接:
因为从9.3版本开始,普通用户也可以结束自己的会话。断开会话的过程还可能出现下面的意外情况:

  1. 筛选会话的过程中,被筛选的会话已经断开,新建立的会话被系统分配了已断开的会话相同的PID,结果把新会话断开;
  2. 同一个用户建立了2个会话,要把这两个会话结束,当筛选出这两个会话的PID的时候,此用户又新建立了多个会话。此时只会结束已经被筛选出PID的会话,而不会将新建立的会话结束。因此要注意前面的限制用户会话数,避免用户在结束会话时创建新的会话。

服务端的实例管理

为多租户进行数据库设计

存在4个不同的方案:

  1. 同一个实例的同一个数据库中,在不同的模式下创建表;
  2. 同一个实例中创建多个数据库;
  3. 同一台物理机或虚拟机上创建多个postgresql实例,监听在不同端口;
  4. 同一个物理机上创建多个虚拟机,每个虚拟机上创建一个postgresql实例;

1,2一般用于将表分离,3,4一般用于资源隔离。

使用多个模式

在PostgreSQL的数据库中,每一组表都有一个自己的命名空间,被称为模式(schema),默认的是public。因此同一个数据库中可以创建多个不同的模式,每个模式底下可以有多张表。
创建模式:
CREATE SCHEMA schema_name;
在此模式下创建表
CREATE TABLE schema_name.table_name (filed1, filed2,.....);
查看当前的模式:
SELECT current_schema;
删除模式:
DROP SCHEMA schema_name;
目前没有切换模式的命令,不同的用户登陆数据库时都会有一个默认的模式,创建用户时如果没有设置,则默认的是public,如果设置了,则使用设置的默认模式。用户的模式设置是通过查找路径search_path变量来确定的。为角色设置默认模式命令如下:
ALTER ROLE role_name SET search_path = 'schema_name';
ALTER USER user_name SET search_path = 'schema_name';
设置完成了以后,登录时,就登录到这个默认的schema里面。

限制某个用户只能在某个模式下处理表的权限
REVOKE ALL ON SCHEMA test FROM public;#取消此用户在其他所有模式下的权限
GRANT ALL ON SCHEMA test TO user1;#给予user1用户在test模式下的所有权限

限制用户user1在模式test下的创建对象权限,以及user1在其他模式下使用对象的权限;
REVOKE ALL ON SCHEMA test FROM public;
GRANT USEAGE ON SCHEMA test TO user1;
GRANT CREATE ON SCHEMA test TO user1;

为模式中的函数对象等设置相应的权限
GRANT SELECT ON month_end_snapshot TO public;

设置用户在模式中的默认权限,创建对象后,对象自动继承对应的用户权限;
ALTER DEFAULT PRIVILEGES FOR USER user1 IN SCHEMA test GRANT SELECT ON TALBES TO PUBLIC;
这里的模式类似于目录,数据表类似于子目录,函数对象等类似于目录下的文件,search_path类似于路径。

给用户分配单独的数据库

为单个用户创建同名的数据库
CREATE USER fred;
CREATE DATABASE fred owner = fred;
但是此时存在问题,默认情况下,新创建的用户拥有登陆其他数据库的能力,其他用户也可以登陆此数据库。因此数据库和角色创建完成后,一定要取消此用户对其他数据库的访问能力,同时取消其他用户访问此数据库的能力。此任务需要在一个事务处理中完成,SQL语句如下:

BEGIN;
REVOKE connect ON DATABASE fred  FROM public;    #取消其他用户连接fred数据库的权限
GRANT connect ON DATABASE fred  TO fred;    #将fred数据的连接权限赋予fred用户
COMMIT;

上面的事务处理中取消了其他用户登陆新建的数据库fred的权限,但是并没有做到取消新建的用户访问其他数据库的能力。(这个问题要等到后面学习了权限管理来解决。)
超级用户可以不受限制的连接到任何数据库和模式。经过处理以后,不在数据库中的用户无法看到库中的表以及任何对象。在库中的角色可以看到表和数据库的属主。

在一个系统上运行多个服务

在RHEL/CentOS/Federo平台上,需要先运行initdb命令先初始化一个数据目录,命令如下:
su - postgres /usr/pgsql/9.6/bin/initdb -D /var/lib/pgsql/<version>/datadir2
修改配置文件data2/postgresql.conf中的端口号,设置参数port=5433,然后用pg_ctl命令启动:
su - postgres /usr/pgsql/9.6/bin/pg_ctl start -D /var/lib/pgsql/<version>/datadir2
此时会使用默认的版本创建一个新的服务,根据端口来区分,如下所示:

tcp        0      0 192.168.1.244:5432      0.0.0.0:*               LISTEN      95999/postmaster    
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      95999/postmaster    
tcp        0      0 127.0.0.1:5433          0.0.0.0:*               LISTEN      112325/postgres     
tcp6       0      0 ::1:5432                :::*                    LISTEN      95999/postmaster    
tcp6       0      0 ::1:5433                :::*                    LISTEN      112325/postgres  

原来配置在9.6/data目录下的postgresql进程监听在5432端口,新配置在9.6/data2目录下的进程监听在5433端口。

以上就是服务控制的所有内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容