Whoami:5年+金融、政府、医疗领域工作经验的DBACertificate:PGCM、OCP、YCPSkill:Oracle、Mysql、PostgreSQL、国产数据库Platform:CSDN、墨天轮、公众号(呆呆的私房菜)
判断题:数据库启动很慢,该怎么办?
A. 等等吧,说不定过一会就起来了。(×)
B. 这么久肯定有问题,尝试多次重启。(×)
C. 了解数据库配置参数和redo进程情况。(√)
我们要去分析数据库启动慢的原因,首先肯定要了解数据库启动时会去做什么事情:
1. 用户请求启动数据库,系统会首先检查环境和数据目录;
2. 接着系统会读取控制文件、加载插件和配置;启动日志和统计进程,加载访问控制文件;
4. 然后系统启动自检和故障恢复进程;
5. 最后系统启动后台工作进程,并进入主循环等待客户端连接,以处理SQL查询和其他数据库操作。
从PostgreSQL的开机过程中分析,数据库启动缓慢的原因大可能在于执行故障恢复操作这一块。我们来看看数据库故障恢复的步骤:
1. PostgreSQL正常运行时会定期创建检查点,这是数据库状态的一个快照,检查点包括了所有已经提交的事务信息,以及哪些数据文件需要更新。当数据库启动时,它会从最后一个检查点开始,读取之后的 wal 日志文件。这些日志文件记录了所有未完成的事务和数据更改;
2. PostgreSQL 会按照日志文件中的记录,重新执行那些在数据库崩溃前已经提交的事务的操作,目的是确保所有已提交的数据更改都被正确地应用到数据库中;
3. 对于未完成的事务,PostgreSQL 在查询时会检查事务的提交状态。如果一个事务在数据库崩溃时还未提交,那么它的更改对其他事务是不可见的。这样,即使这些事务的数据更改已经部分写入磁盘,它们也不会影响其他事务的查询结果。
4. 一旦所有的重做操作完成,PostgreSQL 会确保数据库处于一致的状态,然后数据库就可以开始接受新的客户端连接和事务了。
1. 观察数据库检查点配置:检查的调整会直接影响数据库启动的启动时间,尤其是数据库以非immediate方式关闭的话,那么PostgreSQL是需要更长时间去让数据库达到一致的状态的; 2. 启用检查点日志功能,了解检查点的频率以及数据写入情况; 3. 观察数据库负载情况,了解数据库产生的wal日志的大小和频率; 4. 观察redo进程,评估恢复时间。
-- 调整参数,增加检查点之间的距离shared_buffers = 2048MBwal_keep_size = 1024MBmax_wal_size = 10GBcheckpoint_timeout = 30min-- 创建pg_buffercache扩展,跟踪脏缓冲区情况postgres=# select pg_size_pretty(count(*)*8*1024), isdirty from pg_buffercache; \watch 1-- 创建大表create table test as select i, random() from generate_series(1, 100000000) i;checkpoint;-- 执行长事务begin;delete from test;-- 观察脏缓冲区情况,达到2G左右时Fri 06 Dec 2024 12:47:29 AM CST (every 2s)isdirty pg_size_pretty---------+----------------f | 19 MBt | 1777 MB-- 操作系统层面kill postgres进程# ps -ef | grep postgres# kill -9-- 尝试启动数据库(发现提示stopped waiting!此时千万别慌!不要乱操作!!!)[pg16@host-01 ~]$ pg_ctl startpg_ctl: another server might be running; trying to start server anywaywaiting for server to start....2024-12-06 01:14:41.705 CST [5195] LOG: 00000: redirecting log output to logging collector process2024-12-06 01:14:41.705 CST [5195] HINT: Future log output will appear in directory "log".2024-12-06 01:14:41.705 CST [5195] LOCATION: SysLogger_Start, syslogger.c:715........................................................... stopped waitingpg_ctl: server did not start in time-- 观察数据库日志2024-12-06 01:14:42.983 CST,,,5199,,6751df81.144f,2,,2024-12-06 01:14:41 CST,,0,LOG,00000,"database system was not properly shut down; automatic recovery in progress",,,,,,,,"InitWalRecovery, xlogrecovery.c:926","","startup",,02024-12-06 01:14:42.984 CST,,,5199,,6751df81.144f,3,,2024-12-06 01:14:41 CST,,0,LOG,00000,"recovered replication state of node 1 to 0/288ED138",,,,,,,,"StartupReplicationOrigin, origin.c:808","","startup",,02024-12-06 01:14:42.989 CST,,,5199,,6751df81.144f,4,,2024-12-06 01:14:41 CST,,0,LOG,00000,"redo starts at 5/DCA3E3B8",,,,,,,,"PerformWalRecovery, xlogrecovery.c:1689","","startup",,02024-12-06 01:14:52.989 CST,,,5199,,6751df81.144f,5,,2024-12-06 01:14:41 CST,,0,LOG,00000,"redo in progress, elapsed time: 10.00 s, current LSN: 5/DCD83988",,,,,,,,"PerformWalRecovery, xlogrecovery.c:1702","","startup",,02024-12-06 01:15:02.989 CST,,,5199,,6751df81.144f,6,,2024-12-06 01:14:41 CST,,0,LOG,00000,"redo in progress, elapsed time: 20.00 s, current LSN: 5/DD02A0B0",,,,,,,,"PerformWalRecovery, xlogrecovery.c:1702","","startup",,0-- 查看数据库进程(确认数据库处于恢复状态)[pg16@host-01 pg_wal]$ ps -ef | grep postgres | grep recoveringpg16 5199 5195 96 01:14 ? 00:01:01 postgres: startup recovering 00000001000000060000001C-- 数据库处于recovering状态,可以看看已经应用到哪个wal日志文件,大概评估还需要多久才可以达到数据一致性!
本文内容就到这啦,阅读完本篇,相信你已经掌握如何正确处理PostgreSQL启动慢的问题了吧!我们下篇再见!





