PostgreSQL的存储系统一:控制文件存储结构

Pg 控制文件 pg_control 里存储的数据是一个 ControlFileData 结构。 控制文件尽量保持小于 512 个字节以使其适合一个典型的磁盘驱动的物理簇的大小。这会减少由于电源故障而写控制文件直接失败的可能性。但控制文件的物理大小是 8K ,这个远大于 512 个字节。这样做是为了控制文件格式变化时保持物理大小不变,如果正在读一个不兼容的文件,以使 ReadControlFile 能传递一个合适的错误版本控制文件信息而代替一个读错误。系统里定义了和自己匹配的控制文件版本变量 PG_CONTROL_VERSION ,启动时会做系统和控制文件的匹配校验。

1

控制文件里存储了唯一系统标识符、系统状态数据、数据库启动前系统必须恢复到的最小点、检查服务器硬件架构计算能力的字节排序和浮点数格式、数据库的配置兼容 backend 进程执行的参数、指明类型 timestamp interval time 内部格式的标志、指明不同类型传值( pass-by-value )状态的标志以及所有这些信息的经验和。具体见下面 ControlFileData 结构。

 

typedef struct ControlFileData

{

    /* 唯一系统标识符——保证控制文件和产生 XLOG 文件的数据库一致 */

    uint64      system_identifier ;

    /*

版本标识符信息。保持这些制度在同一个偏移量,特别是 pg_control_version ;如果它们改变了他们就不再有用。(由于历史原因他们必须在文件里是 8 字节,而不是在最前面。)

    pg_control_version 标识 pg_control 自身的格式。

    catalog_version_no 标识系统 catalog 的格式。

    在私有文件里有额外的版本标识符;例如, WAL 日志文件每页包含的 magic 数可以作为 WAL 日志的版本。

      */

    uint32      pg_control_version ;      /* PG_CONTROL_VERSION */

    uint32      catalog_version_no ;      /* see catversion.h */

 

    /* 系统状态数据 */

    DBState        state ;        /* see enum above */

    pg_time_t   time ;         /* time stamp of last pg_control update */

    XLogRecPtr checkPoint ;       /* last check point record ptr */

    XLogRecPtr prevCheckPoint ; /* previous check point record ptr */

 

    CheckPoint checkPointCopy ; /* copy of last check point record */

 

    /*

这两个值确定数据库启动前我们必须恢复到的最小点:

    我们在归档恢复期间刷出数据的时候 minRecoveryPoint 被更新到最后重放的 LSN 。这保证了归档恢复,退出并且在更早的停止位置启动 并恢复到这个位置。如果我们已经从内存里把新的 WAL 记录 X 刷出到磁盘,没有到达 X 我们决不能启动。没有做归档恢复时 minRecoveryPoint 0

    backupStartPoint :如果我们正在从在线备份恢复而且还没有到达备份的结尾, backupStartPoint 是备份开始检查点的 redo 指针。到达备份结尾后置 backupStartPoint 0 并且到达它之前我们不能启动数据库。负责一个布尔值就足够了,但是当我们看到一个 end-of-backup 记录时我们用这个 redo 指针做检查,以保证这个 end-of-backup 记录是我们正在基于其恢复的那个基础备份。

      */

    XLogRecPtr minRecoveryPoint ;

    XLogRecPtr backupStartPoint ;

 

    /* 确定 WAL 能被用于归档或双机热备的参数设置 */

    int         wal_level ;

    int         MaxConnections ;

    int         max_prepared_xacts ;

    int         max_locks_per_xact ;

 

    /*

这些数据用来检查数据库和 backend 进程在其上执行的硬件架构计算能力。我们不需要显式检查字节顺序( endianness ),因为对于一个不同字节顺序的机器控制文件版本会看到问题,但我们需要担心字节对齐和浮点格式。(注意:磁盘存储布局通常依赖于 SHORTALIGN INTALIGN ,但实际上在所有感兴趣的架构上它们是相同的。)

    对于浮点兼容仅测试一个 double 值不是个刀枪不入的测试,但会满足大多数场合。

      */

    uint32      maxAlign ;     /* alignment requirement for tuples */

    double      floatFormat ;  /* constant 1234567.0 */

#define FLOATFORMAT_VALUE   1234567.0

 

    /* 这些数据用来确保数据库的配置兼容 backend 进程执行 */

    uint32      blcksz ;           /* data block size for this DB */

    uint32      relseg_size ;  /* blocks per segment of large relation */

 

    uint32      xlog_blcksz ;  /* block size within WAL files */

    uint32      xlog_seg_size ;    /* size of each WAL segment */

 

    uint32      nameDataLen ;  /* catalog name field width */

    uint32      indexMaxKeys ; /* max number of columns in an index */

 

    uint32      toast_max_chunk_size ;    /* chunk size in TOAST tables */

 

    /* 指明内部 timestamp interval time 内部格式的标志 */

    bool        enableIntTimes ; /* int64 storage enabled? */

 

    /* 指明不同类型 pass-by-value 状态的标志 */

    bool        float4ByVal ;  /* float4 pass-by-value? */

    bool        float8ByVal ;  /* float8, int8, etc pass-by-value? */

 

    /* CRC of all above ... MUST BE LAST! */

    pg_crc32    crc ;

} ControlFileData;

 

    其中的成员 state checkPointCopy checkPoint prevCheckPoint minRecoveryPoint backupStartPoint 需要说明

 

2

成员 state DBState 枚举类型变量。作系统状态指示器。存储于控制文件,如果改变了该枚举类型,必须修改控制文件版本和系统内变量 PG_CONTROL_VERSION 定义见下面。

 

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 ;

 

3

成员 checkPointCopy CheckPoint 类型变量,就是常说的检查点,是最后的那个检查点的拷贝,以备灾难恢复是使用,改变该结构定义要求改变控制文件版本和系统内变量 PG_CONTROL_VERSION 。定义见下面。

 

typedef struct CheckPoint

{

    XLogRecPtr redo ;         /* 开始创建一个检查点时下一个 XLOG 记录的位置 */

    TimeLineID ThisTimeLineID ; /* 当前时间线 */

    uint32      nextXidEpoch ; /* 下一个事务 ID 的高排序位 */

    TransactionId nextXid ;      /* 下一个空闲事务 ID */

    Oid         nextOid ;      /* 下一个空闲 OID */

    MultiXactId nextMulti ;      /* 下一个空闲多事务 ID */

    MultiXactOffset nextMultiOffset ;   /* next free MultiXact offset */

    TransactionId oldestXid ; /* cluster-wide minimum datfrozenxid */

    Oid         oldestXidDB ;  /* database with minimum datfrozenxid */

    pg_time_t   time ;         /* 检查点时间戳 */

 

    /*

仍在运行的最早的事务 ID XID )。只有在从一个在线检查点初始化热备模式时才需要,以使在 GUC 参数 wal_level hot_standby 时我们不用为在线检查点计算运行最早的 XID 。否则设置为常量 InvalidTransactionId

      */

    TransactionId oldestActiveXid ;

} CheckPoint ;

 

4

    成员 checkPoint prevCheckPoint minRecoveryPoint backupStartPoint XLogRecPtr 结构类型的变量。先看 XLogRecPtr 结构类型,用于记录 XLOG 记录在 XLOG 日志文件中的位置,下面是其结构定义:

typedef struct XLogRecPtr

{

    uint32      xlogid ;           /* 逻辑 XLOG 日志文件 ID ,从 0 开始 */

    uint32      xrecoff ;      /* XLOG 日志文件里的字节偏移量 */

} XLogRecPtr ;

 

注意:这儿容易引起理解错乱,这个 xlogid (对应实际 XLOG 文件名字的中间八位)表示逻辑 XLOG 日志文件 ID ,因为组成 XLOG 逻辑文件的实际物理文件远小于 4Gb 。组成对应这个 xlogid 的逻辑日志文件的每一个实际物理文件是一个 XLogSegSize 字节大小的“段”( "segment" ,段号是实际 XLOG 文件名字的后八位)。前面加上用八位表示的一个时间线 ID 、逻辑日志文件号和段号一起标识一个物理的 XLOG 日志文件(“段”)。段号和物理文件里的偏移量由 xrecoff/XLogSegSize xrecoff%XLogSegSize 计算。

 

checkPoint 表示最后的检查点记录指针、 prevCheckPoint 表示最后检查点的前一个检查点记录指针、 minRecoveryPoint 表示数据库从归档恢复的时候的最小恢复点、 backupStartPoint 表示数据库从备份恢复的时候的备份起始点。

 

 ------------
转载请著明出处,来自博客:
blog.csdn.net/beiigang
beigang.iteye.com

猜你喜欢

转载自beigang.iteye.com/blog/1565119