百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

从数据库启动日志看PostgreSQL的崩溃恢复

nanshan 2025-03-06 17:50 13 浏览 0 评论

作者:吴聪


背景


今天碰到朋友问我个问题,数据库启动时日志中的这个“invalid record length at 3/EAA68B8: wanted 24, got 0”里面的wanted 24是啥意思。



而数据库正常启动时的日志其实并不是上面那样,而是如下图所示:



上图的日志是因为数据库异常关闭后重启导致的,例如进程直接被kill。


为了搞清楚上面日志中的那条记录是啥意思,我们来一起研究下数据库异常关闭后恢复的过程。


崩溃恢复概述


首先我们要清楚数据库异常关闭和正常的停库有啥区别。当数据库异常关闭时,数据库的共享缓冲区中的数据还没有来得及刷到磁盘中,必然是会丢失,这个时候启动数据库便是从不正常的状态去启动,也就是我们要研究的崩溃恢复。


之前我也介绍过checkpoint相关的内容, 当PostgreSQL数据库崩溃恢复时,会以最近的checkpoint为基础,不断应用这之后的XLOG日志。为了更好地理解PostgreSQL数据库从崩溃中恢复的过程,我们需要弄清楚以下几个问题:


  • 数据库操作系统如何识别到自己是非正常状态(崩溃状态)
  • 数据库如何找到合适的checkpoint作为基础
  • 为什么应用XLOG日志可以恢复数据库数据
  • 数据库如何应用XLOG日志


数据库状态


在pg中数据库状态分为以下几种(可以通过控制文件查看数据库状态):


typedef enum DBState
{
    DB_STARTUP = 0,/*数据库启动*/
    DB_SHUTDOWNED,/*数据库正常关闭*/
    DB_SHUTDOWNED_IN_RECOVERY,/*数据库在恢复时关闭*/
    DB_SHUTDOWNING,/*数据库启动到正常关闭过程中崩溃*/
    DB_IN_CRASH_RECOVERY,/*数据库在恢复过程中崩溃*/
    DB_IN_ARCHIVE_RECOVERY,/*数据库处于归档恢复*/
    DB_IN_PRODUCTION/*数据库处于正常工作状态,等待接受事务处理*/
} DBState;


当数据库正常关闭时,数据库状态便是shut down,如果是异常关闭,可能会如下所示:

Database cluster state: in production


而每次当PostgreSQL数据库启动时,会首先读取控制文件获取数据库的状态,如果为非正常关闭状态,则会执行崩溃恢复逻辑。


chekpoint相关结构


当数据库进行崩溃恢复时,因为需要恢复异常关闭时丢失的共享内存中的数据,所以需要通过checkpoint来作为基础,不断的应用wal日志来恢复。而checkpoint相关的信息在pg中是存放在控制文件中的,由ControlFileData结构体存储:


typedef struct ControlFileData
{
        ...
    XLogRecPtr    checkPoint;        /*指向最近一次的检查点位置*/
    XLogRecPtr    prevCheckPoint;  /*指向最近一次检查点的前一次检查点的位置*/
    CheckPoint    checkPointCopy; /*最近一次检查点控制信息的副本*/
    XLogRecPtr    minRecoveryPoint; /*归档恢复时必须恢复到的最小LSN*/
    XLogRecPtr    backupStartPoint; /*在线备份时进行的检查点开始LSN*/
    XLogRecPtr    backupEndPoint; /*在线备份时进行的检查点结束LSN*/
        bool        backupEndRequired; /* 用于判断是否基于正确的在线备份集恢复*/
        TimeLineID    minRecoveryPointTLI; /* 必须恢复到的最小时间线 */
    ...
    pg_crc32    crc;
} ControlFileData;


例如下图所示:



一般来说都会选取最近一次的checkpoint作为恢复点,但是会存在一种情况:在执行最近一次的checkpoint是数据库异常关闭了,那么这个检查点可能是不完整的。因此一般还会多存储一个检查点的位置,即prevCheckPoint。


在数据库崩溃恢复过程中,PostgreSQL规定了三个在启动之前必须恢复到的最小位点:


  • minRecoveryPoint:

数据库在归档恢复过程中,minRecoveryPoint被更新为最新被刷新到磁盘的LSN。每次数据库启动时必须已经replay该位置的XLOG日志记录。

  • 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函数对数据库崩溃进行恢复。


其恢复过程大致为:


  1. 初始化内存,启动后台进程。
  2. pg在启动时读取pg_control文件内容。如果state为’in production’,PostgreSQL将进入恢复模式,因为这意味着数据库没有正常停止;如果为’shutdown’,将进入正常启动模式。
  3. pg从相应的WAL段文件中读取最新的检查点记录(位于pg_control文件中),并从记录中获取重做点。如果最新的检查点记录无效(invalid),pg将读取前一个检查点的记录。如果两个记录都不可读,将放弃恢复。注意,从11版本开始不会再存储前一个检查点的记录信息。
  4. 使用合适的资源管理器从重做点开始按顺序读取和重放WAL记录,直到最新WAL文件的最后位置。当遇到备份块时,无论其LSN如何,都会将覆盖相应表的页面。否则仅当此wal记录LSN>相应页面的pd_lsn时,才会重放该WAL记录。


崩溃恢复日志


介绍了这么多,我们再来看看为什么在崩溃恢复时数据库的日志中输出内容是那样的。


因为检测到数据库为异常状态,所以需要从最近一次检查点开始按顺序读取wal日志:



当检测到没有wal日志可以重放时,便会抛出前面的提示:“invalid record length at 3/EAA6580: wanted 24, got 0”。那你可能要问为啥为wanted 24,不是25,26。。。


那我们接着看:



显然这里的24就是SizeOfXLogRecord,其计算方法如下:



这里需要注意,XLogRecord结构体中有2bytes的填充位。


总结


一个简单的数据库启动日志竟然包含着这么多知识!


参考链接:


https://www.pgcon.org/2012/schedule/attachments/258_212_Internals%20Of%20PostgreSQL%20Wal.pdf

http://mysql.taobao.org/monthly/2017/05/03/

src/backend/access/transam/xlog.c

src/backend/access/transam/xlogreader.c

相关推荐

使用nginx配置域名及禁止直接通过IP访问网站

前段时间刚搭建好这个网站,一直没有关注一个问题,那就是IP地址也可以访问我的网站,今天就专门研究了一下nginx配置问题,争取把这个问题研究透彻。1.nginx配置域名及禁止直接通过IP访问先来看n...

如何在 Linux 中使用 PID 号查找进程名称?

在Linux的复杂世界中,进程是系统运行的核心,每个进程都由一个唯一的「进程ID」(PID)标识。无论是系统管理员在排查失控进程,还是开发者在调试应用程序,知道如何将PID映射到对应的进程名称都是一项...

Linux服务器硬件信息查询与日常运维命令总结

1.服务器硬件信息查询1.1CPU信息查询命令功能描述示例lscpu显示CPU架构、核心数、线程数等lscpucat/proc/cpuinfo详细CPU信息(型号、缓存、频率)cat/proc/c...

Ubuntu 操作系统常用命令详解(ubuntu常用的50个命令)

UbuntuLinux是一款流行的开源操作系统,广泛应用于服务器、开发、学习等场景。命令行是Ubuntu的灵魂,也是高效、稳定管理系统的利器。本文按照各大常用领域,详细总结Ubuntu必学...

从 0 到 1:打造基于 Linux 的私有 API 网关平台

在当今微服务架构盛行的时代,API网关作为服务入口和安全屏障,其重要性日益凸显。你是否想过,不依赖商业方案,完全基于开源组件,在Linux上构建一个属于自己的私有API网关平台?今天就带你...

Nginx搭建简单直播服务器(nginx 直播服务器搭建)

前言使用Nginx+Nginx-rtmp-module在Ubuntu中搭建简单的rtmp推流直播服务器。服务器环境Ubuntu16.04相关概念RTMP:RTMP协议是RealTi...

Linux连不上网?远程卡?这篇网络管理指南你不能错过!

大家好!今天咱们聊个所有Linux用户都躲不开的“老大难”——网络管理。我猜你肯定遇到过这些崩溃时刻:新装的Linux系统连不上Wi-Fi,急得直拍桌子;远程服务器SSH连不上,提示“Connecti...

7天从0到上线!手把手教你用Python Flask打造爆款Web服务

一、为什么全网开发者都在疯学Flask?在当今Web开发的战场,Flask就像一把“瑞士军刀”——轻量级架构让新手3天速成,灵活扩展能力又能支撑百万级用户项目!对比Django的“重型装甲”,Flas...

nginx配置文件详解(nginx反向代理配置详解)

Nginx是一个强大的免费开源的HTTP服务器和反向代理服务器。在Web开发项目中,nginx常用作为静态文件服务器处理静态文件,并负责将动态请求转发至应用服务器(如Django,Flask,et...

30 分钟搞定 Docker 安装与 Nginx 部署,轻松搭建高效 Web 服务

在云计算时代,利用容器技术快速部署应用已成为开发者必备技能。本文将手把手教你在阿里云轻量应用服务器上,通过Docker高效部署Nginx并发布静态网站,全程可视化操作,新手也能轻松上手!一、准...

Nginx 配置实战:从摸鱼到部署,手把手教你搞定生产级配置

各位摸鱼搭子们!今天咱不聊代码里的NullPointerException,改聊点「摸鱼必备生存技能」——Nginx配置!先灵魂拷问一下:写了一堆接口却不会部署?服务器被恶意请求打崩过?静态资源加载...

如何使用 Daphne + Nginx + supervisor部署 Django

前言:从Django3.0开始支持ASGI应用程序运行,使Django完全具有异步功能。Django目前已经更新到5.0,对异步支持也越来越好。但是,异步功能将仅对在ASGI下运行的应用程序可用...

Docker命令最全详解(39个最常用命令)

Docker是云原生的核心,也是大厂的必备技能,下面我就全面来详解Docker核心命令@mikechen本文作者:陈睿|mikechen文章来源:mikechen.cc一、Docker基本命令doc...

ubuntu中如何查看是否已经安装了nginx

在Ubuntu系统中,可以通过以下几种方法检查是否已安装Nginx:方法1:使用dpkg命令(适用于Debian/Ubuntu)bashdpkg-l|grepnginx输出...

OVN 概念与实践(德育概念的泛化在理论和实践中有什么弊端?)

今天我们来讲解OVN的概念和基础实践,要理解本篇博客的内容,需要前置学习:Linux网络设备-Bridge&VethPairLinux网络设备-Bridge详解OVS+Fa...

取消回复欢迎 发表评论: