本文转自唐成(osdba) 的博客,原文地址:http://osdbablog.sinaapp.com/535.html


问题的提出

  • 有人问PostgreSQL数据库中刚刚删除的数据能否被恢复?
  • 或更进一步,如果如要在一个事务中做了一系列的更新、删除、插入的操作后,把这个事务提交之后又后悔了,能否恢复到之前的状态?

当然如果数据库有备份,可以直接从备份的数据中恢复,本文讨论的是没有备份的情况下能否恢复。

理论分析

从PostgreSQL多版本实现的原理上,这是有可能的。因为PostgreSQL的多版本原理是旧数据并不删除:

  • 对于删除数据的操作,只是把行上的xmax改成当前的事务id
  • 对于更新操作,只是把原先行上xmax改成当前的事务id,并插入一个新行,而新行上的xmin置为当前的事务id
  • 事务的状态是记录在commit log中的,如果事务提交,只是把commit log中相应的事务状态改成“已提交状态(TRANSACTION_STATUS_COMMITTED )”,如果事务回滚,则把commit log中的事务状态改成“事务回滚(TRANSACTION_STATUS_ABORTED )”

所以从理论上说,只要把在commit log中刚提交事务状态从“TRANSACTION_STATUS_COMMITTED”改成“TRANSACTION_STATUS_ABORTED”,原先的事务就会做废,就能回到事务之前的状态。

但这个恢复有一个前提就是旧版本的数据没有被vacuum垃圾回收进程清理掉,如果旧版本的数据已被vacuum垃圾回收进程给清理掉了,就不能恢复了。所以如果作了删除数据的操作后,马上把数据库停下来,这时autovacuum进程还没有把旧版本的数据给清理掉时,数据是可以恢复的。

但仅仅是把commit log中的事务状态改一下,就能恢复数据吗?答案也是否定的,事情没有这么简单,原因是多版本的可见性判断不仅仅是由commit log中的事务状态的决定的,行上还有t_infomask状态位中的hint信息来决定。如果hint已表示该行上的事务已被提交,则不需要再到commit log中来查看事务的状态了。这个功能主要是为了提高性能,因为到clog中判断行的可见性,而clog中只有8个块是缓存在共享内存中的,如果判断每个行都去查找clog,效率太低了。具体这一部分的内容可以见我的另一篇blog: PostgreSQL中行的可见性判断中t_infomask字段的作用

所以要想恢复数据,还需要把相应表文件中各行上的t_infomask状态中的hint标志位给清除掉之后,数据才能恢复回来。

恢复的工具

因为整个恢复的过程比较复杂,为此我写了一个工具叫pg_fix,放在github上: https://github.com/osdba/pg_fix,供大家研究使用。

首先使用这个工具可以查询某一个表的数据文件中各行的状态:

osdba-mac:pg_fix osdba$ ./pg_fix show_tuple -f 16384
 lp   off  flags lp_len    xmin       xmax      field3   blkid posid infomask infomask2 hoff     oid
---- ----- ----- ------ ---------- ---------- ---------- ----- ----- -------- --------- ----  ----------
   1  8152     1     33       1001       1002          0     0     3        2      4002   24          0
   2  8112     1     33       1001       1002          0     0     4        2      4002   24          0
   3  8072     1     33       1002          0          0     0     3     2002      8002   24          0
   4  8032     1     33       1002          0          0     0     4     2002      8002   24          0

使用这个工具可以清理表的数据文件中的t_infomask中的hint信息,在清理hint状态之前,先查看行上的t_maskinfo状态:

osdba-mac:pg_fix osdba$ ./pg_fix show_tuple -f 16384
 lp   off  flags lp_len    xmin       xmax      field3   blkid posid infomask infomask2 hoff     oid
---- ----- ----- ------ ---------- ---------- ---------- ----- ----- -------- --------- ----  ----------
   1  8152     1     33       1001       1002          0     0     3      502      4002   24          0
   2  8112     1     33       1001       1002          0     0     4      502      4002   24          0
   3  8072     1     33       1002          0          0     0     3     2902      8002   24          0
   4  8032     1     33       1002          0          0     0     4     2902      8002   24          0

然后执行下面命令清除行上的hint状态:

osdba-mac:pg_fix osdba$ ./pg_fix clean_tuple_hint -f 16384

清除完后,我们再看行上的t_infomask状态:

osdba-mac:pg_fix osdba$ ./pg_fix show_tuple -f 16384
 lp   off  flags lp_len    xmin       xmax      field3   blkid posid infomask infomask2 hoff     oid
---- ----- ----- ------ ---------- ---------- ---------- ----- ----- -------- --------- ----  ----------
   1  8152     1     33       1001       1002          0     0     3        2      4002   24          0
   2  8112     1     33       1001       1002          0     0     4        2      4002   24          0
   3  8072     1     33       1002          0          0     0     3     2002      8002   24          0
   4  8032     1     33       1002          0          0     0     4     2002      8002   24          0

查询和改变事务的状态的方法如下:

查询事务xid=11的状态的命令如下:

osdba-mac:pg_fix osdba$ ./pg_fix get_xid_status -f 0000.bkk -x 11
xid(11) status is 1(COMMITTED)

修改事务xid=11的状态的命令如下:

osdba-mac:pg_fix osdba$ ./pg_fix set_xid_status -f 0000.bkk -x 11 -s 0
xid(11) status from 1(COMMITTED) change to 0(IN_PROGRESS)

其中-s后的值表示要把事务改成什么状态,事务的状态值有四种,为0~3,意思如下:

  • #define TRANSACTION_STATUS_IN_PROGRESS 0x00
  • #define TRANSACTION_STATUS_COMMITTED 0x01
  • #define TRANSACTION_STATUS_ABORTED 0x02
  • #define TRANSACTION_STATUS_SUB_COMMITTED 0x03

当然上面使用pg_fix工具直接修改表中数据和commit log中事务的状态都必须是数据库停下来的情况。

另本文的目的主要是为了研究PostgreSQL的一些原理,所以以上这些操作通常不要拿到生产数据库上去试!!!

请在登录后发表评论,否则无法保存。
1楼 xcvxcvsdf
2024-11-13 12:12:43+08

https://aihuishou.tiancebbs.cn/mhsh/ http://cf.lstcxxw.cn/ltxjhs/ https://lanzhongzhen.tiancebbs.cn/ http://gx.lztcxxw.cn/baishan/ https://fenlei.tiancebbs.cn/zhangye/ http://shenghuo.china-bbs.com/ahhz/ https://guangqumen.tiancebbs.cn/ http://ouyu.hftcbmw.cn/dgqz/ http://taiying.njtcbmw.cn/yanbian/ https://dmshi.tiancebbs.cn/ http://fuyang.tjtcbmw.cn/ysjz/ http://shenghuo.china-bbs.com/hljhh/ http://huaguang.jxtcbmw.cn/xjyl/ http://ouyu.hftcbmw.cn/gxyl/ http://jingren.hftcbmw.cn/liuan/ http://huaguang.jxtcbmw.cn/cpq/ http://bjtcxxw.cn/wuwei/

2楼 xcvxcvsdf
2024-10-22 12:47:10+08

http://tuiguang.hntcxxw.cn/jsjz/ https://panshi.tiancebbs.cn/ http://gx.lztcxxw.cn/qiuzhi/ https://jinfeng.tiancebbs.cn/ http://nalei.zjtcbmw.cn/gsdxc/ http://jinqiang.ahtcbmw.cn/cqlp/ http://huaguang.jxtcbmw.cn/zhabeiqu/ http://huilong.sctcbmw.cn/xsjz/ http://huaguang.jxtcbmw.cn/xsjzw/ http://taiying.njtcbmw.cn/wujiaqu/ http://fs.shtcxxw.cn/baoshanqu/ http://yuanbang.tjtcbmw.cn/dandong/ https://ypqzhoubian.tiancebbs.cn/ http://yz.cqtcxxw.cn/heze/ http://nalei.zjtcbmw.cn/cxyzp/ https://xkszwz.tiancebbs.cn/ https://yanchi.tiancebbs.cn/

3楼 xiaowu
2024-04-21 07:32:34+08

穿越火线名字:https://www.nanss.com/mingcheng/1093.html 女士微信名字高雅好听:https://www.nanss.com/mingcheng/645.html 保护野生动物英语作文:https://www.nanss.com/xuexi/639.html 吃鸡名字男生:https://www.nanss.com/mingcheng/510.html 语文教学反思:https://www.nanss.com/gongzuo/929.html 呼啸山庄读后感:https://www.nanss.com/xuexi/1142.html 好看的个性网名:https://www.nanss.com/mingcheng/1234.html 温柔的网名:https://www.nanss.com/mingcheng/814.html 改变不了别人就改变自己的说说:https://www.nanss.com/wenan/1069.html 文明创建工作总结:https://www.nanss.com/gongzuo/1502.html 古风网名男:https://www.nanss.com/mingcheng/870.html 写早晨的优美句子:https://www.nanss.com/xuexi/1100.html 我的梦想:https://www.nanss.com/xuexi/589.html 祝福新人的唯美句子:https://www.nanss.com/yulu/787.html 抖音女生昵称大全:https://www.nanss.com/mingcheng/1187.html 网名非主流:https://www.nanss.com/mingcheng/1409.html 撩妹情话:https://www.nanss.com/yulu/888.html 个性男网名:https://www.nanss.com/mingcheng/1374.html 学生激励自己的句子:https://www.nanss.com/xuexi/1063.html 最近上传的2022年网名:https://www.nanss.com/mingcheng/1458.html 两字网名干净:https://www.nanss.com/mingcheng/666.html 入职自我介绍简单大方:https://www.nanss.com/gongzuo/547.html 父爱的句子:https://www.nanss.com/xuexi/772.html 心愿作文:https://www.nanss.com/xuexi/811.html 怕什么来什么的说说:https://www.nanss.com/wenan/1304.html 新婚贺语:https://www.nanss.com/yulu/1003.html 一家人的群名有创意:https://www.nanss.com/mingcheng/1368.html 生活疲惫无助累的句子:https://www.nanss.com/yulu/1302.html 极品网名:https://www.nanss.com/mingcheng/1457.html 快手昵称:https://www.nanss.com/mingcheng/903.html

© 2010 PostgreSQL中文社区