说说pg中的检查点(checkpoint)之一

本文详细介绍了如何通过pg_stat_bgwriter视图和postgresql.conf中的log_checkpoints配置项来监测PostgreSQL在使用pgbench进行压测时的检查点操作。包括检查点次数统计和具体操作细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       最近一直在使用pgbench对pg进行压测,在压测的过程中,发现checkpoint的发生会对数据库的性能产生极大的影响.

       想看到最近有没有发生checkpoint,有两种比较简单的方式:

        一个是不停的刷新pg_stat_bgwriter这个视图,这个视图中两个字段checkpoints_timed和checkpoints_req直接反映了PG已经发生或是正在发生的checkpoint次数,如果这两个字段的值发生了变化,就说明发生了checkpoint。如果凑巧正在做checkpoint,可以查询这个视图的另外的一个字段buffers_checkpoint,这个字段表明了checkpoint进程刷回了多少个脏的block回磁盘,在做checkpoint的过程中这个字段的结果将会不断累积。在PG的checkpoint进程内部的实现中,如果要做checkpoint,会首先将checkpoints_timed或是checkpoints_req字段关联的统计值加一,然后再来把脏块挨个写回(write)磁盘,每写一个就把相关的统计值加1。一般来说,如果checkpoint_segments设置得足够大(例如128个)并且脏数据块很多,那么在一次做checkpoint的过程可以持续100多秒都是可能的,因此是可以看到buffers_checkpoint这个字段在不断增加的。

       另外一个就是在postgresql.conf中打开log_checkpoints配置项,然后查看日志文件。在checkpoint开始时,会在日志文件中打印一行说checkpoint开始了,然后结束之后也会将本次checkpoint的统计信息打印出来,例如:

LOG:  checkpoint starting: time
LOG:  checkpoint complete: wrote 0 buffers (0.0%); 0 transaction log file(s) added, 0 removed, 0 recycled; write=0.002 s, sync=0.000 s
, total=0.011 s; sync files=0, longest=0.000 s, average=0.000 s

 注意这段日志里面第一行提到了是因为到点了(time)才做的checkpoint。

 

        前面提到的pg_stat_bgwriter视图中两个字段checkpoints_timed和checkpoints_req,在官方的英文文档中说得有些过于简洁,而被翻译成中文之后,结果有些晦涩。对于checkpoints_timed的解释,中文翻译过来是定期执行的检查点数这个基本上是对的,而对于checkpoints_req,英文文档是:Number of requested checkpoints that have been performed。应该是执行被请求的检查点数。至于被谁、在什么情况下请求的?都没有说明。

      对于checkpoints_timed统计的检查点,很容易理解,就是在过了checkpoint_timeout这个配置项指定的时间之后执行的检查点,这个实际上是checkpoint进程主动发起的检查点。他在日志中输出就是上面日志的内容。

      而对于checkpoints_req统计的检查点,实际上可以分为三种:一种是写的WAL距离上次的checkpoint位置已经超过了checkpoint_segments个WAL,那么这个时候需要做一个检查点了;另外一种就是做了比较重量的DML,例如创建了一个database,或是删除了一个database,或是修改了tablespace;最后一种就是用户直接通过SQL执行checkpoint这个命令而触发的检查点。

      checkpoints_req统计的检查点实际上就是checkpoint进程被动执行的。如何来触发checkpoint进程来执行这些检查点呢?很简单:我们知道PG是个多进程的程序,checkpoint的进程信息(包括进程ID)存在了共享内存的hash表中的,是通过名字可以查到的,那么可以获得checkpoint进程的ID、直接通过kill调用来发生某个特定的信号来告诉checkpoint进程需要执行检查点了。实际上也是这样实现的,大家可以看具体的源码。

     那么有个问题:如果过了checkpoint_timeout并且也接到了其他进程做checkpoint的请求了,那么该把谁加一呢?实际代码中是把checkpoints_req加一的。

      另外:PG中发生的checkpoint是否都会被checkpoints_timed和checkpoints_req统计呢?答案是否定的:在PG启动的过程中,postmaster做完了恢复会做一个checkpoint,这个时候还没有其他进程,参见StartupXLOG函数;另外,当PG退出时,checkpoint进程会做一个检查点,这个检查点也是不被统计的。但是,如果打开了log_checkpoints配置项,这两种情况都是会被记录下来的。

<think>嗯,用户遇到了PostgreSQL从库启动时报错“invalid checkpoint record,could not locate a valid checkpoint record”,这个问题需要仔细分析可能的原因。首先,我应该回忆一下这个错误通常是什么引起的。根据经验,这个错误通常和流复制或主库与备库之间的WAL日志不一致有关。 首先,主库和备库的PostgreSQL版本是否一致?如果版本不一致,可能会导致WAL记录格式不兼容,从而无法正确读取查点记录。需要确认用户是否在搭建主从时查过版本匹配情况。 接下来,查流复制的配置是否正确。用户可能在配置recovery.conf或standby.signal文件时参数有误,例如primary_conninfo的连接信息是否正确,确保备库能正确连接到主库。另外,restore_command是否设置正确,如果使用归档恢复,可能需要查归档目录的权限和路径是否正确。 然后,考虑WAL日志的传输问题。主库的WAL日志是否成功传输到了备库?在流复制,备库需要持续接收来自主库的WAL段。如果网络断或者pg_hba.conf配置错误,可能导致传输断,备库无法获取最新的查点记录。此外,查wal_keep_segments或wal_keep_size的设置是否足够,避免主库过早删除还未被备库接收的WAL文件。 还有一种可能是主库在某个查点之后发生了重大变化,而备库的基础备份是在此之前进行的,导致备库无法找到有效的查点。这时候可能需要重新做一个基础备份,使用pg_basebackup重新创建备库的数据目录,并确保备份完成后主库的WAL日志仍然保留足够的时间供备库同步。 另外,用户是否手动修改过备库的数据目录文件?比如误删除了某些WAL文件或者数据文件,也可能导致查点记录无效。需要查备库的pg_wal目录是否有完整的WAL文件,并确认没有人为的破坏。 此外,主库和备库之间的时间同步是否正常?如果时间不同步,可能导致某些基于时间戳的查出现问题,但这种情况可能比较少见。 最后,如果以上步骤都确认无误,可能需要查看PostgreSQL的日志文件,寻找更详细的错误信息。主库和备库的日志可能会有更具体的线索,例如连接错误、权限问题或者文件损坏等。 总结下来,可能的解决步骤包括查版本一致性、验证流复制配置、确保WAL日志传输正常、重新创建基础备份以及查文件完整性等。需要引导用户一步步排查这些可能性,从而找到根本原因并解决问题。</think>PostgreSQL从库启动时出现`invalid checkpoint record, could not locate a valid checkpoint record`错误,通常与**流复制配置**或**WAL日志完整性**有关。以下是逐步排查与解决方法: --- ### **1. 基本原因分析** 此错误表明从库无法在主库传输的WAL日志找到有效的查点记录,可能原因包括: - 主从库PostgreSQL版本不一致 - 流复制参数配置错误 - WAL日志未正确传输(网络断、权限问题) - 基础备份已过期或损坏 --- ### **2. 关键排查步骤** #### **步骤1:验证主从库版本一致性** - **查版本号**: ```bash # 主库执行 psql -c "SELECT version();" # 从库执行(若可启动) psql -c "SELECT version();" ``` **要求**:主从库的PostgreSQL主版本号必须一致(如14.x与14.x兼容,14.x与15.x不兼容)。 --- #### **步骤2:查流复制配置** - **从库的`postgresql.conf`**: - 确保`primary_conninfo`参数正确指向主库: ```ini primary_conninfo = 'host=<主库IP> port=5432 user=replication_user password=xxx' ``` - 查`wal_level`是否为`replica`: ```ini wal_level = replica ``` - **从库的`standby.signal`文件**(PG12+)或`recovery.conf`(PG11及更早): - 确认文件存在且包含`standby_mode = on`(旧版本)。 --- #### **步骤3:验证WAL日志传输** - **主库查WAL发送状态**: ```sql SELECT * FROM pg_stat_replication; ``` 观察从库是否在连接列表,`state`应为`streaming`。 - **从库查WAL接收状态**: ```sql SELECT * FROM pg_stat_wal_receiver; ``` 查`status`是否正常,`received_lsn`是否持续更新。 --- #### **步骤4:查WAL日志保留** - **主库的`wal_keep_size`设置**: ```ini wal_keep_size = 10GB # 确保足够保留未传输的WAL日志 ``` 如果主库过早删除未传输的WAL,从库会丢失连续性。 --- #### **步骤5:重建从库(终极解决方案)** 如果上述步骤无效,可能是基础备份已损坏,需重新创建从库: 1. **停止从库**: ```bash pg_ctl stop -D /path/to/standby/data ``` 2. **删除从库数据目录**: ```bash rm -rf /path/to/standby/data/* ``` 3. **重新生成基础备份**: ```bash pg_basebackup -h <主库IP> -U replication_user -D /path/to/standby/data -P -v -R ``` 4. **启动从库**: ```bash pg_ctl start -D /path/to/standby/data ``` --- ### **3. 附加注意事项** - **权限问题**:确保从库用户(如`replication_user`)在主库的`pg_hba.conf`有REPLICATION权限。 - **网络连通性**:使用`telnet <主库IP> 5432`验证端口是否开放。 - **日志分析**:查主从库的日志文件(`log_directory`)以获取更具体的错误信息。 --- ### **总结** 此错误通常由 **WAL日志连续性断** 或 **配置错误** 导致。按顺序排查版本、配置、WAL传输状态,若仍无法解决,重建从库是最可靠的修复方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值