问题:
一个开发环境数据库无法访问,开发同事登录到服务器查看,发现存储数据库的挂载点存储使用率达到了100%,导致数据库宕机且无法再启动,他最终找到是pg_wal把存储撑爆了,然后就直接rm掉了,当然也就导致了数据库启动报错。
解决方案:
发现问题后首先查看环境现状,操作系统CentOS7.5,数据库版本10.3,发现这是个开发环境没有配置WAL归档,所以不能从归档恢复,另外也没有配置standby,无法进行failover,最后确定了3个恢复方案,如下优先级从高到底尝试,其目的是不丢失数据,或尽量减少丢失的数据。
-
通过工具恢复rm掉的wal,如果能全部恢复肯定是最好,但是这种可能性不大,求其次恢复Latest checkpoint’s REDO WAL file以来的文件也没问题,极限情况下只恢复Latest checkpoint’s REDO WAL file即可(数据库干净关闭)。出问题的服务器操作系统是CentOS7,且数据库目录在根上,默认使用的是XFS文件系统,没有使用xfsdump进行过备份,也就不能xfsrestore进行还原了,网上找其它的工具试图恢复,但是没有成功,由于此环境是开发环境,丢失一些数据关系不大,但是需要尽快启动以免影响开发进度,所以文件恢复就没有深究了。
-
使用pg_resetwal重置wal,首先查看控制文件是否正常(pg_controldata -D $PGDATA),如果控制文件没问题,可以进行重置(pg_resetwal PG数据目录),启动数据库,这种方式会丢失未checkpoint的wal数据,丢失的数据多少受checkpoint_timeout参数的影响。
pg_resetwal使用注意事项:
- 出于安全原因,你必须在命令行中指定数据目录,pg_resetwal不使用环境变量PGDATA;
- 这个命令不能在服务器正在运行时被使用,如果在数据目录中发现一个服务器锁文件,pg_resetwal将拒绝启动;
- 如果服务器崩溃那么一个锁文件可能会被残留,需先移除锁文件且确认没有服务器进程仍然存活,然后再运行pg_resetwal;
- 使用pg_resetwal后,数据库可能包含由于部分提交事务产生的不一致数据,应当立刻备份你的数据、初始化实例后,重新恢复,并检查不一致修复之;
- pg_resetwal是服务端工具,不能在客户端运行;
- 如果pg_resetwal无法通过读取pg_control确定合适的值时,才需要选项-c、-l、-m、-x、-O、-o、-e等参数,具体使用可参考官方文档说明,其实这些参数值的获取也可以自己再封装一个脚本来自动获取,实在不行只能使用-f参数了,但是恢复的数据库还是值得怀疑,一次立即的备份和重新恢复是势在必行的,在你备份之前不要在该数据库中执行任何数据修改操作,因为任何这样的动作都可能使破坏更严重。
- 从全备中恢复,这个环境每天有一个全备,这也是最后的方案,数据可能丢失数小时。
问题朔源:
导致数据库宕机的原因是pg_wal下面的预写日志没有及时的清理,但是max_wal_size设置了上限,按理数据库会自动进行清理,且这环境没有配置归档、物理流复制和逻辑流复制,经与开发同事沟通此环境安装了一个第三方的插件实时同步数据到kafka,这就能解释通为什么pg_wal会爆掉了,由于kafka长时间未消费或异常导致与数据库的逻辑复制槽断开,又未进行清理致使wal累积。清理wal有很多方式,其中使用pg_archivecleanup工具比较稳妥。