PostgreSQL 启动异常

最近一个客户的生产环境遇到这样的一个问题。背景大致说明下,就是机房断电,所有的服务器都异常关机,在电力恢复之后,重启服务器发现数据库服务不能正常启动。由于这个节点的数据库很多,而且定时备份很久之前都坏了,有效的备份都是几个月之前的,并且备份还不是全备,只有部分做了备份,很多边缘的数据库都没有备份,甚至有很多都是与业务紧密相关的,不能说重新初始化一个实例,然后根据备份直接去解压还原。下面是数据库启动的日志信息

2023-07-11 16:11:02.991 CST [1046] 0    LOG:  starting PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2023-07-11 16:11:02.991 CST [1046] 0    LOG:  listening on IPv4 address "0.0.0.0", port 5432
2023-07-11 16:11:02.992 CST [1046] 0    LOG:  listening on IPv6 address "::", port 5432
2023-07-11 16:11:02.993 CST [1046] 0    LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-07-11 16:11:02.995 CST [1046] 0    LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2023-07-11 16:11:03.016 CST [1279] 0    LOG:  database system was interrupted; last known up at 2023-07-10 18:26:58 CST
2023-07-11 16:11:03.884 CST [1279] 0    LOG:  invalid record length at 7/B5F401B8: wanted 24, got 0
2023-07-11 16:11:03.884 CST [1279] 0    LOG:  invalid primary checkpoint record
2023-07-11 16:11:03.884 CST [1279] 0    PANIC:  could not locate a valid checkpoint record
2023-07-11 16:11:03.887 CST [1046] 0    LOG:  startup process (PID 1279) was terminated by signal 6: Aborted
2023-07-11 16:11:03.887 CST [1046] 0    LOG:  aborting startup due to startup process failure
2023-07-11 16:11:03.913 CST [1046] 0    LOG:  database system is shut down
2023-07-11 16:21:01.627 CST [20792] 0    LOG:  starting PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2023-07-11 16:21:01.627 CST [20792] 0    LOG:  listening on IPv4 address "0.0.0.0", port 5432
2023-07-11 16:21:01.627 CST [20792] 0    LOG:  listening on IPv6 address "::", port 5432
2023-07-11 16:21:01.628 CST [20792] 0    LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-07-11 16:21:01.630 CST [20792] 0    LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2023-07-11 16:21:01.645 CST [20794] 0    LOG:  database system was interrupted; last known up at 2023-07-10 18:26:58 CST
2023-07-11 16:21:01.850 CST [20794] 0    LOG:  invalid record length at 7/B5F401B8: wanted 24, got 0
2023-07-11 16:21:01.850 CST [20794] 0    LOG:  invalid primary checkpoint record
2023-07-11 16:21:01.850 CST [20794] 0    PANIC:  could not locate a valid checkpoint record
2023-07-11 16:21:01.851 CST [20792] 0    LOG:  startup process (PID 20794) was terminated by signal 6: Aborted
2023-07-11 16:21:01.851 CST [20792] 0    LOG:  aborting startup due to startup process failure
2023-07-11 16:21:01.884 CST [20792] 0    LOG:  database system is shut down

从上面的日志信息中我们可以找到关键的几个信息:
LOG:  invalid record length at 7/B5F401B8: wanted 24, got 0
LOG:  invalid primary checkpoint record
PANIC:  could not locate a valid checkpoint record

从上面的信息中我们可以了解到是找不到有效的检查点记录。网上搜索给出的解释是 WAL 日志文件损坏,这种一般是操作系统故障或者是硬件损坏会引起这个问题。服务器直接关机这种情况我们说实战演练用的也比较多,因为经常需要进行演练断电或者高可用测试都需要进行系统关机,但是关机之后重启系统服务还是可以正常启动的,但是这里直接启动不了了,再者我们知道服务器就算关机后,数据库也会进行启动恢复的。这一点不论是 PostgreSQL 还是别的什么数据库都是有这种机制在底层实现的。

下面我们简单描述下数据库异常关闭后恢复的过程:
当数据库异常关闭时,数据库的共享缓冲区中的数据还没有来得及刷到磁盘中,必然是会丢失,这个时候启动数据库便是从不正常的状态去启动,也就是我们要研究的崩溃恢复。我们说几乎任意一个数据库都有类似检查点这种操作,当 PostgreSQL 数据库崩溃恢复时,会以最近的 checkpoint 为基础,不断应用这之后的重做日志。为了更好地理解 PostgreSQL 数据库从崩溃中恢复的过程,我们需要弄清楚以下几个问题:
数据库操作系统如何识别到自己是非正常状态崩溃状态?
数据库如何找到合适的 checkpoint 作为基础?
为什么应用重做日志可以恢复数据库数据?
数据库如何应用重做日志?

PostgreSQL 数据库的状态有如下几种
DB_STARTUP = 0 /*数据库启动*/
DB_SHUTDOWNED /*数据库正常关闭*/
DB_SHUTDOWNED_IN_RECOVERY /*数据库在恢复时关闭*/
DB_SHUTDOWNING /*数据库启动到正常关闭过程中崩溃*/
DB_IN_CRASH_RECOVERY /*数据库在恢复过程中崩溃*/
DB_IN_ARCHIVE_RECOVERY /*数据库处于归档恢复*/
DB_IN_PRODUCTION /*数据库处于正常工作状态,等待接受事务处理*/

当数据库正常关闭时,数据库状态便是 shut down,如果是异常关闭,可能会如下所示:
Database cluster state: in production 而每次当 PostgreSQL 数据库启动时,会首先读取控制文件获取数据库的状态,如果为非正常关闭状态,则会执行崩溃恢复逻辑。
Chekpoint 相关结构:当数据库进行崩溃恢复时,因为需要恢复异常关闭时丢失的共享内存中的相关数据,所以需要通过 checkpoint 检查点来作为基础,不断的应用重做日志即 wal 日志来恢复。而 checkpoint 相关的信息在 PostgreSQL 中是存放在控制文件中的。
XLogRecPtr checkPoint /*指向最近一次的检查点位置*/
XLogRecPtr prevCheckPoint /*指向最近一次检查点的前一次检查点的位置*/
CheckPoint checkPointCopy /*最近一次检查点控制信息的副本*/
XLogRecPtr minRecoveryPoint /*归档恢复时必须恢复到的最小 LSN*/
XLogRecPtr backupStartPoint /*在线备份时进行的检查点开始 LSN*/
XLogRecPtr backupEndPoint /*在线备份时进行的检查点结束 LSN*/
bool backupEndRequired /* 用于判断是否基于正确的在线备份集恢复*/
TimeLineID minRecoveryPointTLI /* 必须恢复到的最小时间线 */

/usr/pgsql-14/bin/pg_controldata -D /home/postgres/pgsql-14/data/ | grep checkpoint
一般来说都会选取最近一次的 checkpoint 作为恢复点,但是会存在这样的一种特殊情况:在执行最近一次的 checkpoint 时数据库异常关闭了,那么这个检查点可能是不完整的。因此一般还会多存储一个检查点的位置,即 prevCheckPoint。在数据库崩溃恢复过程中,PostgreSQL 规定了三个在启动之前必须恢复到的最小位点:
minRecoveryPoint:数据库在归档恢复过程中,minRecoveryPoint 会被更新为最新被刷新到磁盘的最近一次检查点 LSN。每次数据库启动时必须已经 replay 该位置的重做日志记录。
backupStartPoint:数据库在线备份开始时,会调用 pg_start_backup 函数执行一次 checkpoint,并生成 backup_label 文件。当使用在线备份集进行恢复时,backupStartPoint 就是上述 checkpoint 记录对应的 LSN,当达到了该 LSN,该值置为 0,在置为 0 之前,数据库不能启动。该值被记录在 backup_label 文件中如下,直到在线备份结束,pg_stop_backup 将该文件删除。这样就保证了在备份过程中,数据库崩溃了,可以默认从备份开始时的日志检查点开始恢复。
backupEndPoint:当数据库从一个备库做的在线备份集进行恢复时,backupEndPoint 表示备份结束的 LSN,当达到该 LSN,该值置为 0,在置为 0 之前,数据库不能启动。

崩溃恢复具体过程:每次 postmaster 进程启动时,都会调用 StartupXLOG 函数对数据库崩溃进行恢复。其恢复过程大致为:
初始化内存,启动后台进程。
PostgreSQL 在启动时读取 pg_control 文件内容。如果 state 为 ’in production’,PostgreSQL 将进入恢复模式,因为这意味着数据库没有正常停止;如果为 ’shutdown’,将进入正常启动模式。PostgreSQL 从相应的 WAL 段文件中读取最新的检查点记录,该位置位于 pg_control 文件中,并从记录中获取重做点。如果最新的检查点记录无效 invalid,PostgreSQL 将读取前一个检查点的记录。如果两个记录都不可读,将放弃恢复。

那么既然我们已经大致了解了是什么原因之后,如何恢复呢?
1、首先我们需要备份当前数据目录到一个新的位置。
2、强制重置 WAL 日志,/usr/pgsql-14/bin/pg_resetwal -f -D /home/postgres/pgsql-14/data/
3、再次去启动数据库 /usr/pgsql-14/bin/pg_ctl restart -D /home/postgres/pgsql-14/data/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60533.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【划分型DP-约束划分个数】【hard】力扣410. 分割数组的最大值

给定一个非负整数数组 nums 和一个整数 k ,你需要将这个数组分成 k 个非空的连续子数组,使得这 k 个子数组各自和的最大值 最小。 返回分割后最小的和的最大值。 子数组 是数组中连续的部份。 示例 1: 输入:nums [7,2,5,10,8]…

python高级之面向对象编程

一、面向过程与面向对象 面向过程和面向对象都是一种编程方式,只不过再设计上有区别。 1、面向过程pop: 举例:孩子上学 1. 妈妈起床 2. 妈妈洗漱 3. 妈妈做饭 4. 妈妈把孩子叫起来 5. 孩子起床 6. 孩子洗漱 7. 孩子吃饭 8. 妈妈给孩子送学校…

shell脚本(1)

免责声明 学习视频来自B 站up主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下代码、网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 Shell脚本 建立一个sh脚本…

《DiffusionDet: Diffusion Model for Object Detection》ICCV2023

摘要 本文提出了一种新的框架DiffusionDet,它将目标检测任务表述为从带噪声的边界框到目标边界框的去噪扩散过程(如图一所示)。在训练阶段,目标边界框逐渐扩散到随机分布,模型学习逆转这一加噪过程。在推理阶段&#…

ISAAC SIM踩坑记录--ROS2相机影像发布

其实这个例子官方和大佬NVIDIA Omniverse和Isaac Sim笔记5:Isaac Sim的ROS接口与相机影像、位姿真值发布/保存都已经有详细介绍了,但是都是基于ROS的,现在最新的已经是ROS2,这里把不同的地方简单记录一下。 搭建一个简单的场景&a…

outlook邮箱关闭垃圾邮件——PowerAutomate自动化任务

微软邮箱反垃圾已经很强大了非常敏感,自家的域名的邮件都能给扔到垃圾邮箱里,但还是在本地增加了一层垃圾邮箱功能,然后垃圾邮箱并没有提示,导致错过很多通知,本身并没有提供关闭的功能,但微软有个Microsof…

「Py」Python基础篇 之 Python都可以做哪些自动化?

✨博客主页何曾参静谧的博客📌文章专栏「Py」Python程序设计📚全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定…

candence: 原理图生成网表时报错:Duplicate Pin name “xxx“

原理图生成网表时报错:Duplicate Pin name “xxx” 这个错误的意思是,原理图中管脚命名重复 解决这个问题的方法: 1、绘制元件的时候不要用相同的管脚名,比如GND等的,就稍加个后缀做区分2、就是将管脚属性修改为 &qu…

Diffusion Policy——斯坦福机器人UMI所用的扩散策略:从原理到其编码实现(含Diff-Control、ControlNet详解)

前言 本文一开始是属于此文《UMI——斯坦福刷盘机器人:从手持夹持器到动作预测Diffusion Policy(含代码解读)》的第三部分,考虑后Diffusion Policy的重要性很高,加之后续还有一系列基于其的改进工作 故独立成本文,且写的过程中 …

计算机网络学习笔记-3.2介质访问控制

文章目录 介质访问控制静态划分信道 动态分配信道轮询访问介质访问控制随机访问介质访问控制ALOHA协议简介ALOHA协议的工作原理 介质访问控制 介质访问控制(MAC,Medium Access Control),质访问控制的目的是确保多个设备能够高效、…

GitCode光引计划有奖征文大赛

一、活动介绍 GitCode平台汇聚了众多杰出的G-Star项目,它们犹如璀璨星辰,用各自的故事和成就,为后来者照亮前行的道路。我们诚邀广大开发者、项目维护者及爱好者,共同撰写并分享项目在GitCode平台上托管的体验,挖掘平…

深入理解接口测试:实用指南与最佳实践5.0(三)

✨博客主页: https://blog.csdn.net/m0_63815035?typeblog 💗《博客内容》:.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 📢博客专栏: https://blog.csdn.net/m0_63815035/cat…

使用electron-egg把vue项目在linux Ubuntu环境下打包并安装运行

electron-egg一个入门简单、跨平台、企业级桌面软件开发框架https://www.kaka996.com/electron-egg 跳转地址 1,使用 git下载代码到本地,如果没有git需要进行安装 # gitee git clone https://gitee.com/dromara/electron-egg.git # github git clone https://github.com/dro…

DAY112代码审计PHP开发框架POP链利用Yii反序列化POP利用链

一、pop1链的跟踪 1、路由关系 2、漏洞触发口unserialize(base64_decode($data)); 2、__destruct(),魔术法方法调用close函数方法 3、未找到利用链,尝试__call魔术方法 4、逆推找call_user_func 函数 第一部分 namespace yii\db; class BatchQueryResu…

Maven 构建项目

Maven 是一个项目管理和构建工具,主要用于 Java 项目。它简化了项目的构建、依赖管理、报告生成、发布等一系列工作。 构建自动化:Maven 提供了一套标准化的构建生命周期,包括编译、测试、打包、部署等步骤,通过简单的命令就可以执…

任务调度中心-XXL-JOB使用详解

目录 详解 调度中心 执行器 原理 快速入门 源码仓库地址 1.初始化数据库 2.配置调度中心 1.解压源码 2.需改配置文件 3.启动调度中心 3.配置执行器 1.引入pom依赖 2.修改配置文件 3.执行器组件配置 4.部署执行器项目 4.开发第一个任务 BEAN模式(类…

ROM修改进阶教程------安卓14 安卓15去除app签名验证的几种操作步骤 详细图文解析

在安卓14 安卓15的固件中。如果修改了系统级别的app。那么就会触发安卓14 15的应用签名验证。要么会导致修改的固件会进不去系统,或者进入系统有bug。博文将从几方面来解析去除安卓14 15应用签名验证的几种方法。 💝💝💝通过博文了解: 1💝💝💝-----安卓14去除…

批量规范化与ResNet-paddle

批量规范化与ResNet——paddle部分 本文部分为paddle框架以及部分理论分析,torch框架对应代码可见批量规范化与ResNet import paddle print("paddle version:",paddle.__version__)paddle version: 2.6.1批量规范化 批量规范化(Batch Norma…

从零开始快速构建Vue3项目

一、技术选型 组件大类 具体插件 vue3插件 相关插件开发文档 基础架构搭建 初始项目搭建、打包构件工具:vite开始 | Vite路由管理及菜单权限封装vue-router介绍 | Vue Router状态管理Pinia介绍 | Pinia 中文文档API请求及异常封装axiosUI框架 element-uihttps…

74HC245

74HC245:典型的CMOS型缓冲门电路 在这里用于增加电压