PostgreSQL 通过SQL接口关闭、重启数据库

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 标签 PostgreSQL , 重启 , 信号 , postmaster.pid , pg_reload_conf() 背景 如何通过SQL接口直接关闭数据库,或者重启数据库? 关闭和重启数据库是一个风险较大的操作,如果能通过SQL来关闭,重启数据库,当然是很难想象的,因为SQL通常是使用接口,而不是管理接口。当然并不是数据库做不到通过SQL管理数据库,而是这确实是风险较大且并不是数据

标签

PostgreSQL , 重启 , 信号 , postmaster.pid , pg_reload_conf()


背景

如何通过SQL接口直接关闭数据库,或者重启数据库?

关闭和重启数据库是一个风险较大的操作,如果能通过SQL来关闭,重启数据库,当然是很难想象的,因为SQL通常是使用接口,而不是管理接口。当然并不是数据库做不到通过SQL管理数据库,而是这确实是风险较大且并不是数据库核心的能努力。

但是为了方便管理,数据库还是提供了很多管理函数(通过SQL调用)。例如:

https://www.postgresql.org/docs/11/functions-info.html

那么能不能通过SQL接口来关闭,或者重启数据库呢?(通常我们需要登陆到数据库所在的操作系统,执行pg_ctl来实现)

关闭数据库的底层实现

实际上关闭数据库是往postgres master进程(数据库启动时的父进程)发送信号,进程在收到信号后会进行相应的操作。可以通过看postmaster.c代码或通过man postgres得到这个信息:

man postgres

To terminate the postgres server normally, the signals SIGTERM, SIGINT, or SIGQUIT can be used.   
The first will wait for all clients to terminate before quitting,   
the second will forcefully disconnect all clients,   
and the third will quit immediately without proper shutdown, resulting in a recovery run during restart.   

如何获得postmaster进程pid呢?

直接读postmaster.pid文件即可得到:

postgres=# select * from pg_read_file('postmaster.pid');  
        pg_read_file          
----------------------------  
 30503                     +  
 /data01/digoal/pg_root8001+  
 1549031862                +  
 8001                      +  
 .                         +  
 0.0.0.0                   +  
   8001001  39288833       +  
 ready                     +  
   
(1 row)  

30503 为postmaster进程的PID。

关闭数据库就是往这个PID发送信号(SIGTERM 正常关闭, SIGINT 快速关闭, or SIGQUIT 暴力关闭)。

发送信号给数据库进程

src/backend/utils/adt/misc.c

1、发送给postmaster进程SIGHUP信号,用于reload conf。

/*  
 * Signal to reload the database configuration  
 *  
 * Permission checking for this function is managed through the normal  
 * GRANT system.  
 */  
Datum  
pg_reload_conf(PG_FUNCTION_ARGS)  
{  
        if (kill(PostmasterPid, SIGHUP))  
        {  
                ereport(WARNING,  
                                (errmsg("failed to send signal to postmaster: %m")));  
                PG_RETURN_BOOL(false);  
        }  
  
        PG_RETURN_BOOL(true);  
}  

2、发送给普通进程,用于cancel query或terminate session

/*  
 * Signal to terminate a backend process.  This is allowed if you are a member  
 * of the role whose process is being terminated.  
 *  
 * Note that only superusers can signal superuser-owned processes.  
 */  
Datum  
pg_terminate_backend(PG_FUNCTION_ARGS)  
{  
        int                     r = pg_signal_backend(PG_GETARG_INT32(0), SIGTERM);  
  
        if (r == SIGNAL_BACKEND_NOSUPERUSER)  
                ereport(ERROR,  
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),  
                                 (errmsg("must be a superuser to terminate superuser process"))));  
  
        if (r == SIGNAL_BACKEND_NOPERMISSION)  
                ereport(ERROR,  
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),  
                                 (errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend"))));  
  
        PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);  
}  
/*  
 * Signal to cancel a backend process.  This is allowed if you are a member of  
 * the role whose process is being canceled.  
 *  
 * Note that only superusers can signal superuser-owned processes.  
 */  
Datum  
pg_cancel_backend(PG_FUNCTION_ARGS)  
{  
        int                     r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);  
  
        if (r == SIGNAL_BACKEND_NOSUPERUSER)  
                ereport(ERROR,  
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),  
                                 (errmsg("must be a superuser to cancel superuser query"))));  
  
        if (r == SIGNAL_BACKEND_NOPERMISSION)  
                ereport(ERROR,  
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),  
                                 (errmsg("must be a member of the role whose query is being canceled or member of pg_signal_backend"))));  
  
        PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);  
}  

src/backend/utils/adt/misc.c

/*  
 * Send a signal to another backend.  
 *  
 * The signal is delivered if the user is either a superuser or the same  
 * role as the backend being signaled. For "dangerous" signals, an explicit  
 * check for superuser needs to be done prior to calling this function.  
 *  
 * Returns 0 on success, 1 on general failure, 2 on normal permission error  
 * and 3 if the caller needs to be a superuser.  
 *  
 * In the event of a general failure (return code 1), a warning message will  
 * be emitted. For permission errors, doing that is the responsibility of  
 * the caller.  
 */  
#define SIGNAL_BACKEND_SUCCESS 0  
#define SIGNAL_BACKEND_ERROR 1  
#define SIGNAL_BACKEND_NOPERMISSION 2  
#define SIGNAL_BACKEND_NOSUPERUSER 3  
static int  
pg_signal_backend(int pid, int sig)  
{  
。。。  
        if (proc == NULL)  
        {  
                /*  
                 * This is just a warning so a loop-through-resultset will not abort  
                 * if one backend terminated on its own during the run.  
                 */  
                ereport(WARNING,  
                                (errmsg("PID %d is not a PostgreSQL server process", pid)));  
                return SIGNAL_BACKEND_ERROR;  
        }  
。。。  

PG内部并没有开放一个SQL接口来停库,所以我们需要自己写一个

vi pg_fast_stop.c  
  
  
#include <signal.h>   
#include "fmgr.h"    
#include "postgres.h"   
  
PG_MODULE_MAGIC;    
    
PG_FUNCTION_INFO_V1(pg_fast_stop);    
    
  
Datum  
pg_fast_stop(PG_FUNCTION_ARGS)  
{  
        if (kill(PostmasterPid, SIGINT))  
        {  
                ereport(WARNING,  
                                (errmsg("failed to send signal to postmaster: %m")));  
                PG_RETURN_BOOL(false);  
        }  
  
        PG_RETURN_BOOL(true);  
}  
gcc -O3 -Wall -Wextra -I /home/digoal/postgresql-11.1/src/include -g -fPIC -c ./pg_fast_stop.c -o pg_fast_stop.o  
gcc -O3 -Wall -Wextra -I /home/digoal/postgresql-11.1/src/include -g -shared pg_fast_stop.o -o libpg_fast_stop.so   
  
cp libpg_fast_stop.so $PGHOME/lib/  
psql   
  
create or replace function pg_fast_stop() returns int as '$libdir/libpg_fast_stop.so', 'pg_fast_stop' language C STRICT;    

试用:

postgres=# select pg_fast_stop();  
 pg_fast_stop
------------  
          1  
(1 row)  
  
数据库已关机  
  
postgres=# \dt  
FATAL:  terminating connection due to administrator command  
server closed the connection unexpectedly  
        This probably means the server terminated abnormally  
        before or while processing the request.  
The connection to the server was lost. Attempting reset: Failed.  
!> \q  

如何实现SQL接口重启数据库呢?

因为往POSTMASTER PID发送信号只能关闭数据库,无法重启数据库。那么怎么实现重启呢?

1、#restart_after_crash = on # reinitialize after backend crash?

利用普通用户进程被KILL -9来自动重启,这个是postmaster守护进程自动执行的重启动作。

2、利用plsh存储过程语言,直接调用pg数据库操作系统的pg_ctl命令来重启。

https://github.com/petere/plsh

参考

https://github.com/petere/plsh

https://www.postgresql.org/docs/11/functions-info.html

https://www.postgresql.org/docs/11/functions-admin.html

src/backend/utils/adt/misc.c

 

免费领取阿里云RDS PostgreSQL实例、ECS虚拟机

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
14天前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
3天前
|
存储 关系型数据库 数据库
【赵渝强老师】PostgreSQL的数据库集群
PostgreSQL的逻辑存储结构涵盖了数据库集群、数据库、表、索引、视图等对象,每个对象都有唯一的oid标识。数据库集群是由单个PostgreSQL实例管理的所有数据库集合,共享同一配置和资源。集群的数据存储在一个称为数据目录的单一目录中,可通过-D选项或PGDATA环境变量指定。
|
17天前
|
关系型数据库 分布式数据库 数据库
PostgreSQL+Citus分布式数据库
PostgreSQL+Citus分布式数据库
49 15
|
14天前
|
SQL 存储 Linux
从配置源到数据库初始化一步步教你在CentOS 7.9上安装SQL Server 2019
【11月更文挑战第8天】本文介绍了在 CentOS 7.9 上安装 SQL Server 2019 的详细步骤,包括系统准备、配置安装源、安装 SQL Server 软件包、运行安装程序、初始化数据库以及配置远程连接。通过这些步骤,您可以顺利地在 CentOS 系统上部署和使用 SQL Server 2019。
|
15天前
|
SQL 存储 Linux
从配置源到数据库初始化一步步教你在CentOS 7.9上安装SQL Server 2019
【11月更文挑战第7天】本文介绍了在 CentOS 7.9 上安装 SQL Server 2019 的详细步骤,包括系统要求检查与准备、配置安装源、安装 SQL Server 2019、配置 SQL Server 以及数据库初始化(可选)。通过这些步骤,你可以成功安装并初步配置 SQL Server 2019,进行简单的数据库操作。
|
25天前
|
SQL 数据采集 监控
局域网监控电脑屏幕软件:PL/SQL 实现的数据库关联监控
在当今网络环境中,基于PL/SQL的局域网监控系统对于企业和机构的信息安全至关重要。该系统包括屏幕数据采集、数据处理与分析、数据库关联与存储三个核心模块,能够提供全面而准确的监控信息,帮助管理者有效监督局域网内的电脑使用情况。
18 2
|
25天前
|
SQL 关系型数据库 数据库
PostgreSQL性能飙升的秘密:这几个调优技巧让你的数据库查询速度翻倍!
【10月更文挑战第25天】本文介绍了几种有效提升 PostgreSQL 数据库查询效率的方法,包括索引优化、查询优化、配置优化和硬件优化。通过合理设计索引、编写高效 SQL 查询、调整配置参数和选择合适硬件,可以显著提高数据库性能。
147 1
|
28天前
|
存储 关系型数据库 MySQL
MySQL vs. PostgreSQL:选择适合你的开源数据库
在众多开源数据库中,MySQL和PostgreSQL无疑是最受欢迎的两个。它们都有着强大的功能、广泛的社区支持和丰富的生态系统。然而,它们在设计理念、性能特点、功能特性等方面存在着显著的差异。本文将从这三个方面对MySQL和PostgreSQL进行比较,以帮助您选择更适合您需求的开源数据库。
104 4
|
30天前
|
SQL JSON Java
没有数据库也能用 SQL
SPL(Structured Process Language)是一款开源软件,允许用户直接对CSV、XLS等文件进行SQL查询,无需将数据导入数据库。它提供了标准的JDBC驱动,支持复杂的SQL操作,如JOIN、子查询和WITH语句,还能处理非标准格式的文件和JSON数据。SPL不仅简化了数据查询,还提供了强大的计算能力和友好的IDE,适用于多种数据源的混合计算。
|
27天前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
53 0
下一篇
无影云桌面