暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PanweiDB数据库丢失clog问题如何解决

迈泊思船长 2025-06-23
118

一、为什么需要clog

PanweiDB的默认存储引擎有着独特的MVCC机制,由于其多版本的特性,在进行可见性判断时,需要获取事务的状态,即元组中 t_xmin 和 t_xmax 的状态,需要clog来记录事务的状态,从而判断其可见性。
内存里的访问远远快于磁盘读写,因此PanweiDB的很多机制都是运行时候在内存,然后定期持久化到磁盘。因此clog也有一块内存区域便于高效访问,即clog buffers,它也属于共享内存的这部分,平时更新clog是内存中进行的,然后满足条件后会调用pg_fsync刷数据到磁盘上的clog文件,或者等待checkpoint刷数据。数据库启动时会从磁盘的pg_xact目录下读取事务状态加载到clog buffers,并且运行过程中,vacuum会定时将不再使用的clog文件清理。

PanweiDB中通过clog来存储事务的状态。所以,当在PanweiDB中如果想要取消一个执行了很长时间的事务,基本上是瞬间完成的,而不是像Oracle中一样需要等到undo表空间中内容回滚完,因为PanweiDB里只需要将事务的状态由IN_PROGRESS修改为ABORTED即可。

二、clog的内容

在PanweiDB里定义了几种需要提交日志clog来记录事务的状态,从而判断其可见性,共有四种事务状态。分别是:IN_PROGRESS、COMMITED、ABORTED和SUB_COMMITED。例如事务正在运行中,那么它的状态就是IN_PROGRESS。全部是0是初始状态,SUB_COMMITTED状态表示已提交的子事务,其父事务尚未提交或中止。每个状态只需要两位(2 bit)就可以表示。因此四个事务的状态就占用了8 bit 即一个字节。

=4种事务状态=====
#define TRANSACTION_STATUS_IN_PROGRESS 0x00
#define TRANSACTION_STATUS_COMMITTED 0x01
#define TRANSACTION_STATUS_ABORTED 0x02
#define TRANSACTION_STATUS_SUB_COMMITTED 0x03

三、发生丢失clog的问题如何伪造clog恢复数据

某次数据库的主机发生了异常重启,等服务器以及数据库拉起之后,查询某张业务表的时候,发现直接报了确失clog的错误,这种情况下,表的数据其实还是在数据页里的,但是由于clog缺失了,数据库无法通过clog里的事务状态,来判断可见性,所以我们读不到这部分的数据。
如果有可用的备份,最简单的恢复方法无疑是通过物理备份和连续归档,做PITR恢复数据,但是如果没有可用备份的话,则可能需要其他的方式恢复,例如:伪造缺失的clog文件。

[SLRU] DETAIL: Could not open file “pg_clog/000000000000”: No such file or directory

查看对应数据目录下的pg_clog路径时,发现目录下只有一个00000000001C的文件,这明显缺失了很多clog文件,正常情况下,pg_clog文件是从000000000000开始,依次递增,是12位的十六进制数字组成,从000000000000到00000000001C应该总共29个文件。
因为缺失的文件暂时无法找回,而这些文件里记录了事务的状态信息,我们无法确认这里边每一个事物的状态,因此我们就以所有事务都可见,创建缺失的clog。可以用dd进行伪造这个数据块(数据块伪造全部提交)。

for i in {1..262144}; do printf '\125'; done > 000000000000
for i in {1..262144}; do printf '\125'; done > 000000000002
... ...
for i in {1..262144}; do printf '\125'; done > 00000000001B

使用如下命令查看创建的文件是否符合预期:

od -xv 000000000002 | head
od -xv 000000000002 | tail

如果大致结果如下,除第一列外,均为5555,则标志文件符合预期。

0000000 5555 5555 5555 5555 5555 5555 5555 5555
0000020 5555 5555 5555 5555 5555 5555 5555 5555
0000040 5555 5555 5555 5555 5555 5555 5555 5555
0000060 5555 5555 5555 5555 5555 5555 5555 5555
0000100 5555 5555 5555 5555 5555 5555 5555 5555
0000120 5555 5555 5555 5555 5555 5555 5555 5555
0000140 5555 5555 5555 5555 5555 5555 5555 5555
0000160 5555 5555 5555 5555 5555 5555 5555 5555
0000200 5555 5555 5555 5555 5555 5555 5555 5555
0000220 5555 5555 5555 5555 5555 5555 5555 5555

注意创建完文件后需要更改权限,把属主和权限更改为和原来的一致。否则可能识别不到文件。
全部伪造完之后,可以尝试重启数据库。再次查询之前查询报错的表,发现可以访问了,但是需要注意的是,这种方式,把所有的事务状态置为可见,可能引起表中存在重复数据,此方式恢复后,需要业务处理重复数据的问题。(第一首选肯定是用备份恢复)

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论