写点什么

PostgreSQL 误删数据怎么办?

  • 2019-08-28
  • 本文字数:3623 字

    阅读完需:约 12 分钟

PostgreSQL 误删数据怎么办?

本文经授权转载自 PostgreSQL 中文社区。


PostgreSQL 并未有闪回和数据误删除保护的功能,但是在一些场景下也可以实现。


此方法仅仅针对 DML 操作有效,DDL 操作(drop/truncate 等会将数据页面删除)无法找回数据。由于 PG 是多版本实现机制,因此数据仍然都在,只是不可见而已,vacuum_defer_cleanup_age 可以防止最近这些事务的元祖被删除,即保留这些事务操作的元组,可以闪回到这些操作的任意时间点

开始准备数据

test=# select pg_current_wal_lsn();
pg_current_wal_lsn
0/2003B58(1 row)
test=# create table lzzhang(id int);
CREATE TABLE
test=# insert into lzzhang values(1);
INSERT 0 1
test=# insert into lzzhang values(2);
INSERT 0 1
test=# insert into lzzhang values(3);
INSERT 0 1
test=# insert into lzzhang values(4);
INSERT 0 1
test=# insert into lzzhang values(5);
INSERT 0 1
test=# insert into lzzhang values(6);
INSERT 0 1
test=# select xmin, xmax, cmin, cmax, * from lzzhang;xmin | xmax | cmin | cmax | id——+——+——+——+—-
588 | 0 | 0 | 0 | 1
589 | 0 | 0 | 0 | 2
590 | 0 | 0 | 0 | 3
591 | 0 | 0 | 0 | 4
592 | 0 | 0 | 0 | 5
593 | 0 | 0 | 0 | 6
(6 rows)
复制代码

回滚 Insert

分析 redo,根据时间找到自己的错误操作,并找到对应的事务号


./pg_waldump -b -s 0/2003B58 -p dj
rmgr: Transaction len (rec/tot): 34/ 34, tx: 589, lsn: 0/0201A660, prev 0/0201A620, desc: COMMIT 2019-03-26 10:55:05.685536 CST
rmgr: Heap len (rec/tot): 59/ 59, tx: 590, lsn: 0/0201A688, prev 0/0201A660, desc: INSERT off 3
blkref #0: rel 1663/16392/16393 fork main blk 0
rmgr: Transaction len (rec/tot): 34/ 34, tx: 590, lsn: 0/0201A6C8, prev 0/0201A688, desc: COMMIT 2019-03-26 10:55:07.749260 CST
rmgr: Heap len (rec/tot): 59/ 59, tx: 591, lsn: 0/0201A6F0, prev 0/0201A6C8, desc: INSERT off 4
blkref #0: rel 1663/16392/16393 fork main blk 0
rmgr: Transaction len (rec/tot): 34/ 34, tx: 591, lsn: 0/0201A730, prev 0/0201A6F0, desc: COMMIT 2019-03-26 10:55:09.893856 CST
rmgr: Heap len (rec/tot): 59/ 59, tx: 592, lsn: 0/0201A758, prev 0/0201A730, desc: INSERT off 5
blkref #0: rel 1663/16392/16393 fork main blk 0
rmgr: Transaction len (rec/tot): 34/ 34, tx: 592, lsn: 0/0201A798, prev 0/0201A758, desc: COMMIT 2019-03-26 10:55:11.917570 CST
rmgr: Heap len (rec/tot): 59/ 59, tx: 593, lsn: 0/0201A7C0, prev 0/0201A798, desc: INSERT off 6
复制代码


此示例中,我们回滚 5 和 6 的数据。根据 wal 信息找到事务号为 592。


关闭数据库[lzzhang@lzzhang-pc bin]$ ./pg_resetwal -D dj -x 592启动数据库
复制代码


查询


test=# select xmin, xmax, cmin, cmax, * from lzzhang;
xmin | xmax | cmin | cmax | id------+------+------+------+----588 | 0 | 0 | 0 | 1589 | 0 | 0 | 0 | 2590 | 0 | 0 | 0 | 3591 | 0 | 0 | 0 | 4
复制代码


5/6 的数据已经没有了。增长事务号,看看情况!!!


test=# select * from txid_current(); txid_current--------------592(1 row)
复制代码


test=# select * from txid_current();txid_current-------------- 593(1 row)
复制代码


test=# select * from txid_current();txid_current--------------594
复制代码


test=# select xmin, xmax, cmin, cmax, * from lzzhang;xmin | xmax | cmin | cmax | id------+------+------+------+----588 |    0 |    0 |    0 |  1 589 |    0 |    0 |    0 |  2590 |    0 |    0 |    0 |  3591 |    0 |    0 |    0 |  4592 |    0 |    0 |    0 |  5593 |    0 |    0 |    0 |  6
复制代码


由于 5/6 仍然在数据库中,所以 5/6 又可见了。

回滚 delete

删除数据


test=# select pg_current_wal_lsn();pg_current_wal_lsn--------------------0/3000190(1 row)

复制代码


test=# delete from lzzhang where id = 5 or id = 6;DELETE 2
复制代码


找到事物号(595)


rmgr: Heap        len (rec/tot):     59/   299, tx:        595, lsn: 0/030001B8, prev 0/03000180, desc: DELETE off 5 KEYS_UPDATED , blkref #0: rel 1663/16392/16393 blk 0 FPW
复制代码


rmgr: Heap        len (rec/tot):     54/    54, tx:        595, lsn: 0/030002E8, prev 0/030001B8, desc: DELETE off 6 KEYS_UPDATED , blkref #0: rel 1663/16392/16393 blk 0
复制代码


rmgr: Transaction len (rec/tot):     34/    34, tx:        595, lsn: 0/03000320, prev 0/030002E8, desc: COMMIT 2019-03-26 11:00:23.410557 CST
复制代码


回滚数据


关闭数据库[lzzhang@lzzhang-pc bin]$ ./pg_resetwal -D dj -x 595启动数据库
复制代码


查看数据


test=# select xmin, xmax, cmin, cmax, * from lzzhang;xmin | xmax | cmin | cmax | id------+------+------+------+----588 |    0 |    0 |    0 |  1589 |    0 |    0 |    0 |  2590 |    0 |    0 |    0 |  3591 |    0 |    0 |    0 |  4592 |  595 |    0 |    0 |  5593 |  595 |    0 |    0 |  6
复制代码


提升事务号,5/6 又被删除


test=# select * from txid_current();txid_current--------------595(1 row)
复制代码


test=# select * from txid_current();txid_current--------------596(1 row)
复制代码


test=# select xmin, xmax, cmin, cmax, * from lzzhang;xmin | xmax | cmin | cmax | id------+------+------+------+----588 |    0 |    0 |    0 |  1589 |    0 |    0 |    0 |  2590 |    0 |    0 |    0 |  3591 |    0 |    0 |    0 |  4(4 rows)
复制代码

回滚 update

回滚 update 的操作类似,就不在讲述。

回滚 drop table

回滚后表可见,但是数据已经没有了 test=# select * from zz;ERROR: could not open file “base/16392/16396”: 没有那个文件或目录根据你的需要回滚/闪回指定操作,然后使用 txid_current()提升事物号,并不影响数据库整体的可用性。

确定数据仍然存在

安装 pageinspect 插件

create extension pageinspect

检查数据是否存在

查看目前表中的内容


test=# select xmin, xmax, cmin, cmax, * from lzzhang;xmin | xmax | cmin | cmax | id——+——+——+——+—–588 | 0 | 0 | 0 | 1589 | 0 | 0 | 0 | 2590 | 0 | 0 | 0 | 3597 | 0 | 0 | 0 | 100
复制代码


查看表的 page 内容(无效/不可见的元组都可以查看到)


test=# select * from heap_page_items(get_raw_page(‘lzzhang’, ‘main’, 0));lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data—-+——–+———-+——–+——–+——–+———-+——–+————-+————+——–+——–+——-+————1 | 8160 | 1 | 28 | 588 | 0 | 0 | (0,1) | 1 | 2304 | 24 | | | \x010000002 | 8128 | 1 | 28 | 589 | 0 | 0 | (0,2) | 1 | 2304 | 24 | | | \x020000003 | 8096 | 1 | 28 | 590 | 0 | 0 | (0,3) | 1 | 2304 | 24 | | | \x030000004 | 8064 | 1 | 28 | 591 | 597 | 0 | (0,7) | 16385 | 1280 | 24 | | | \x040000005 | 8032 | 1 | 28 | 592 | 595 | 0 | (0,5) | 8193 | 1280 | 24 | | | \x050000006 | 8000 | 1 | 28 | 593 | 595 | 0 | (0,6) | 8193 | 1280 | 24 | | | \x060000007 | 7968 | 1 | 28 | 597 | 0 | 0 | (0,7) | 32769 | 10496 | 24 | | | \x64000000
复制代码


vacuum 后查看 page 数据 vacuum lzzhang;


test=# select * from heap_page_items(get_raw_page(‘lzzhang’, ‘main’, 0));lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data—-+——–+———-+——–+——–+——–+———-+——–+————-+————+——–+——–+——-+————1 | 8160 | 1 | 28 | 588 | 0 | 0 | (0,1) | 1 | 2304 | 24 | | | \x010000002 | 8128 | 1 | 28 | 589 | 0 | 0 | (0,2) | 1 | 2304 | 24 | | | \x020000003 | 8096 | 1 | 28 | 590 | 0 | 0 | (0,3) | 1 | 2304 | 24 | | | \x030000004 | 7 | 2 | 0 | | | | | | | | | |5 | 0 | 0 | 0 | | | | | | | | | |6 | 0 | 0 | 0 | | | | | | | | | |7 | 8064 | 1 | 28 | 597 | 0 | 0 | (0,7) | 32769 | 10496 | 24 | | | \x64000000(7 rows)
复制代码


4/5/6 已经被 vacuum 掉,通过 waldump 可以找到对应的事务号的元祖已经不在,所有无法找回。


作者简介:


张连壮,多年 PostgreSQL 数据库内核研发经验,高可用/数据复制方面经验较为丰富,目前主要从事分布式数据库 Citus 相关工作,CitusDB 中国【站主】专注于 Citus 技术分享的全信息平台。


原文链接:


https://mp.weixin.qq.com/s/FbA8haWVOwRcw4CKNP0Vig


2019-08-28 11:336187

评论

发布
暂无评论
发现更多内容

将进一步提高数字人民币的可得性 构建分布式数字身份认证体系

CECBC

Micro Focus 发布年度安全运营报告,洞察后疫情时代企业安全运营新趋势

中小企业自媒体为何难做:定位不准期望值过高

石头IT视角

redis--数据库实现

en

2021下半年全新京东商城亿级并发架构设计,不学习你就OUT了!!

Java 程序员 面试 计算机 京东

直播报名 | 超低延时直播架构解析

百度开发者中心

最佳实践 方法论 活动 直播

如何高效掌控K8s资源变化?K8s Informer实现机制浅析

腾源会

云原生 k8s

T-BOX专业分享

SOA开发者

丧心病狂!阿里内部Spring Cloud高薪笔记流失,GitHub夜获星百万

Java 程序员 面试 计算机 阿里巴巴‘

python之深浅拷贝

秦时明月

工业互联网的两种极端想法和两点反思

iNeuOS工业互联网操作系统

大数据 物联网 智能制造 iNeuOS工业互联网

阿里独家!GitHub上点击量超百万的「操作系统和计算机网络」PDF震撼开源

Java 程序员 面试 计算机 Alibaba

如何做竞品分析?

石云升

产品经理 产品思维 9月日更 产品分析

数字化的田亩里,华为正写一首陶渊明的诗

脑极体

腾讯圆梦,我整理收集了这份“2021常见Java面试真题汇总”

Java 架构 编程语言 java面试

云信小课堂 | 聊天室内容审核很头疼?3步解决!

网易云信

人工智能 AI 视频

被 Docker 日志坑惨了

AlwaysBeta

Docker 容器 运维

【重磅】Apache InLong(incubating) 发布 0.10.0 版本

腾源会

Apache 开源 InLong

Alibaba竟流出全套的Java核心技术手册,看过的人都说好!

Java 程序员 架构 面试 计算机

我的9年开源之路:395 Patch、20+Feature,背后只有努力与热爱

腾源会

腾讯云 开源 虚拟化 Linux内核 kvm

深入探讨区块链价值及其对世界的影响

CECBC

20+互联网公司Java面试考点大全,全网首发,应有尽有

Java 程序员 编程语言 java面试

大众汽车迟到的软件优先思维

SOA开发者

DPDK分析学习之全网唯一的DPDK教学课程丨虚拟化高性能专家之路

Linux服务器开发

网络协议 虚拟化 Linux服务器开发 DPDK 高性能网络

芯慌遇上造车热,国产芯片的机会到了?

脑极体

2022前端react面试题汇总

buchila11

React

Nebula Graph 源码解读系列 | Vol.01 Nebula Graph Overview

NebulaGraph

如何用时序数据库 CTSDB 与 TARS 结合,解决海量监控数据难题

腾源会

数据库 大数据 开源 TARS CTSDB

进程和处理机管理中的进程控制

Regan Yue

操作系统 进程 9月日更 进程控制

从技术到商业:2021 DEMO CHINA创新中国峰会正式开启

创业邦

支持 10 亿日流量的基础设施:当 Apahce APISIX 遇上腾讯

腾源会

腾讯云 开源 APISIX OTeam

PostgreSQL 误删数据怎么办?_数据库_张连壮_InfoQ精选文章