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

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

nanshan 2025-03-06 17:50 15 浏览 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

相关推荐

0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)

文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...

ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes

为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...

生产环境starrocks 3.1存算一体集群部署

集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...

在CentOS上添加swap虚拟内存并设置优先级

现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...

国产深度(deepin)操作系统优化指南

1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...

postgresql-15.4 多节点主从(读写分离)

1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...

Docker 容器 Java 服务内存与 GC 优化实施方案

一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...

虚拟内存设置、解决linux内存不够问题

虚拟内存设置(解决linux内存不够情况)背景介绍  Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...

Elasticsearch性能调优(5):服务器配置选择

在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...

Es如何落地

一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...

针对Linux内存管理知识学习总结

现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...

MySQL进阶之性能优化

概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...

Linux Cgroups(Control Groups)原理

LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...

linux 常用性能优化参数及理解

1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...

如何在 Linux 中使用 Sysctl 命令?

sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...

取消回复欢迎 发表评论: