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

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: PostgreSQL 通过SQL接口关闭、重启数据库

背景

如何通过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

PostgreSQL 许愿链接

您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.

9.9元购买3个月阿里云RDS PostgreSQL实例

PostgreSQL 解决方案集合

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
12天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
51 10
|
29天前
|
SQL 存储 BI
【软件设计师备考 专题 】数据库语言(SQL)
【软件设计师备考 专题 】数据库语言(SQL)
90 0
|
1月前
|
SQL 数据库
sql server中创建数据库和表的语法
sql server中创建数据库和表的语法
18 1
|
12天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
76 6
|
1天前
|
SQL Oracle 关系型数据库
sql语句创建数据库
在创建数据库之前,请确保你有足够的权限,并且已经考虑了数据库的安全性和性能需求。此外,不同的DBMS可能有特定的最佳实践和配置要求,因此建议查阅相关DBMS的官方文档以获取更详细和准确的信息。
|
1天前
|
SQL 缓存 数据库
sql 数据库优化
SQL数据库优化是一个复杂且关键的过程,涉及多个层面的技术和策略。以下是一些主要的优化建议: 查询语句优化: 避免全表扫描:在查询时,尽量使用索引来减少全表扫描,提高查询速度。 使用合适的子查询方式:子查询可能降低查询效率,但可以通过优化子查询的结构或使用连接(JOIN)替代子查询来提高性能。 简化查询语句:避免不必要的复杂查询,尽量使SQL语句简单明了。 使用EXISTS替代IN:在查询数据是否存在时,使用EXISTS通常比IN更快。 索引优化: 建立合适的索引:对于经常查询的列,如主键和外键,应创建相应的索引。同时,考虑使用覆盖索引来进一步提高性能。 避免过多的索引:虽然索引可以提高查询
|
9天前
|
SQL 数据库
数据库SQL语言实战(二)
数据库SQL语言实战(二)
|
9天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
33 3
|
12天前
|
SQL 监控 数据库
数据库管理与电脑监控软件:SQL代码优化与实践
本文探讨了如何优化数据库管理和使用电脑监控软件以提升效率。通过SQL代码优化,如使用索引和调整查询语句,能有效提高数据库性能。同时,合理设计数据库结构,如数据表划分和规范化,也能增强管理效率。此外,利用Python脚本自动化收集系统性能数据,并实时提交至网站,可实现对电脑监控的实时性和有效性。这些方法能提升信息系统稳定性和可靠性,满足用户需求。
41 0
|
12天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例

相关产品

  • 云原生数据库 PolarDB