云貝教育 |【技術文章】PostgreSQL中誤刪除數據怎么辦(一)

原文鏈接:【PostgreSQL】PostgreSQL中誤刪除數據怎么辦(一) - 課程體系 - 云貝教育 (yunbee.net)

在我們學習完PG的MVCC機制之后,對于DML操作,被操作的行其實并未被刪除,只能手工vacuum或自動vacuum觸發才會清理掉這些無效數據,也就是死元組。

基于這種機制,在發生死元組清理動作之前,只需要將其中不可見的行中的數據解析出來,或者發生臟讀,就可以獲取到誤刪除的數據。雖然PG不支持臟讀,但今天介紹的pg_dirtyread插件,可以實現臟讀。

一、安裝pg_dirtyread

下載地址

GitHub - df7cb/pg_dirtyread: Read dead but unvacuumed tuples from a PostgreSQL relation

這個網頁上有詳細的安裝說明

編譯安裝

unzip pg_dirtyread-master.zip
cd pg_dirtyread-master/
make
make install

二、使用示例

2.1、在對應庫創建EXTENSION
create extension pg_dirtyread ;

2.2、創建表并禁用autovacuum
testdb=# CREATE TABLE t1 (id int, name text);
CREATE TABLE
2.3、插入并通過heap_page_items查看數據
testdb=# INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'),(3,'ccc');
INSERT 0 3
testdb=#
testdb=# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid,t_data FROM heap_page_items(get_raw_page('t1', 0));tuple | t_xmin | t_xmax | t_cid | t_ctid | t_data
-------+--------+--------+-------+--------+----------------------------1 |   1104 |      0 |     0 | (0,1)  | \x0100000000000000096161612 |   1104 |      0 |     0 | (0,2)  | \x0200000000000000096262623 |   1104 |      0 |     0 | (0,3)  | \x030000000000000009636363
(3 rows)
2.4、刪除數據
testdb=# DELETE FROM t1 WHERE id = 1;
DELETE 1
testdb=# DELETE FROM t1 WHERE id = 2;
DELETE 1testdb=# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid,t_data FROM heap_page_items(get_raw_page('t1', 0));tuple | t_xmin | t_xmax | t_cid | t_ctid | t_data
-------+--------+--------+-------+--------+----------------------------1 |   1104 |   1105 |     0 | (0,1)  | \x0100000000000000096161612 |   1104 |   1106 |     0 | (0,2)  | \x0200000000000000096262623 |   1104 |      0 |     0 | (0,3)  | \x030000000000000009636363
(3 rows)

這里發現被刪除的數據還在塊中

2.5、 發現數據被誤刪除后第一時間關掉表上的vacuum

這一步很關鍵!!!

這一步很關鍵!!!

這一步很關鍵!!!

ALTER TABLE t1 SET (
autovacuum_enabled = false, toast.autovacuum_enabled = false
);

2.6、查看表vacuum情況
testdb=# \x
Expanded display is on.
testdb=# select * from pg_stat_all_tables where relname='t1';
-[ RECORD 1 ]-------+-------
relid               | 49546
schemaname          | public
relname             | t1
seq_scan            | 3
seq_tup_read        | 6
idx_scan            |
idx_tup_fetch       |
n_tup_ins           | 3
n_tup_upd           | 0
n_tup_del           | 2
n_tup_hot_upd       | 0
n_live_tup          | 1
n_dead_tup          | 2
n_mod_since_analyze | 5
n_ins_since_vacuum  | 3
last_vacuum         |
last_autovacuum     |
last_analyze        |
last_autoanalyze    |
vacuum_count        | 0
autovacuum_count    | 0
analyze_count       | 0
autoanalyze_count   | 0

last_vacuum和last_autovacuum都是空的,表示還未被vacuum過。

2.7、使用pg_dirtyread查看表,dead為t表示數據已?經刪除
testdb=# SELECT * FROM pg_dirtyread('t1')
AS t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boole an,id int, name text);tableoid | ctid  | xmin | xmax | cmin | cmax | dead | id | name
----------+-------+------+------+------+------+------+----+------49546 | (0,1) | 1104 | 1105 |    0 |    0 | t    |  1 | aaa49546 | (0,2) | 1104 | 1106 |    0 |    0 | t    |  2 | bbb49546 | (0,3) | 1104 |    0 |    0 |    0 | f    |  3 | ccc
(3 rows)

刪除數據后,需要查詢一下,pg_dirtyread中的dead列才會更新。也就是pg_dirtyread需要掃描一次表中的page才知道該行是不是被修改過。

testdb=# delete from t1;
DELETE 3testdb=# SELECT * FROM pg_dirtyread('t1')
AS t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int, name text);
tableoid | ctid | xmin | xmax | cmin | cmax | dead | id | name
----------+-------+------+------+------+------+------+-----+-----
49541 | (0,1) | 1102 | 1108 | 0 | 0 | f | 1 | aaa
49541 | (0,2) | 1102 | 1108 | 0 | 0 | f | 2 | bbb
49541 | (0,3) | 1102 | 1108 | 0 | 0 | f | 3 | ccc
(3 rows)testdb=# select * from t1;
id | name
-----+-----
(0 rows)testdb=# SELECT * FROM pg_dirtyread('t1')
AS t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int, name text);
tableoid | ctid | xmin | xmax | cmin | cmax | dead | id | name
----------+-------+------+------+------+------+------+-----+-----
49541 | (0,1) | 1102 | 1108 | 0 | 0 | t | 1 | aaa
49541 | (0,2) | 1102 | 1108 | 0 | 0 | t | 2 | bbb
49541 | (0,3) | 1102 | 1108 | 0 | 0 | t | 3 | ccc
(3 rows)
2.8 恢復到某個時間

如果做不完全恢復,即恢復數據到某個時刻,需要使用函數pg_xact_commit_timestamp將事務ID進行轉換。

testdb=# alter system set track_commit_timestamp=on;
ALTER SYSTEM#刪除一條數據
testdb=# select * from t1;
id | name
----+------
5 | EEE
(1 row)testdb=# delete from t1;
DELETE 1#查看刪除時間
testdb=# SELECT pg_xact_commit_timestamp(xmin) xmin_time
,pg_xact_commit_timestamp(xmax) xmax_time
,*
FROM pg_dirtyread('t1')
AS t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int, name text)
where xmax<>0;
-[ RECORD 1 ]----------------------------
xmin_time | 2023-12-03 16:27:03.830358+08
xmax_time | 2023-12-06 10:10:29.115887+08
tableoid | 49776
ctid | (0,2)
xmin | 7207
xmax | 7235
cmin | 0
cmax | 0
dead | f
id | 5
name | EEE

xmax_time 就是數據具體刪除時間

2.9、pg_dirtyread還支持被刪除的列
testdb=# select * from t1;
id | name
----+------
3 | ccc
(1 row)testdb=#
testdb=# ALTER TABLE t1 DROP COLUMN name;
ALTER TABLE
testdb=# SELECT * FROM pg_dirtyread('t1') t1(id int, dropped_2 text);
id | dropped_2
----+-----------
1 | aaa
2 | bbb
3 | ccc
3 | ccc
(4 rows)testdb=# select * from t1;
id
----
3
(1 row)

三、如果表上已經發生了vacuum

3.1、對表進行vacuum回收死元組
postgres=# vacuum t1;
VACUUM
3.2、查看塊中的數據被清理
testdb=# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid,t_data F
ROM heap_page_items(get_raw_page('t1', 0));
tuple | t_xmin | t_xmax | t_cid | t_ctid | t_data
-------+--------+--------+-------+--------+----------------------------1 |        |        |       |        |2 |        |        |       |        |3 |        |        |       |        |4 |   1110 |      0 |     0 |  (0,4) | \x030000000000000009636363
(4 rows)

3.3、再次用pg_dirtyread查看死元組的數據已經被清理了

testdb=# \x
Expanded display is on.
testdb=# select * from pg_stat_all_tables where relname='t1';
-[ RECORD 1 ]-------+------------------------------
relid | 49546
schemaname | public
relname | t1
seq_scan | 8
seq_tup_read | 33
idx_scan |
idx_tup_fetch |
n_tup_ins | 4
n_tup_upd | 0
n_tup_del | 3
n_tup_hot_upd | 0
n_live_tup | 1
n_dead_tup | 0
n_mod_since_analyze | 7
n_ins_since_vacuum | 0
last_vacuum | 2023-12-01 14:55:44.099392+0821 last_autovacuum |
last_analyze |
last_autoanalyze |
vacuum_count | 1
autovacuum_count | 0
analyze_count | 0
autoanalyze_count | 0testdb=# SELECT * FROM pg_dirtyread('t1') t1(id int, dropped_2 text);
id | dropped_2
----+-----------
3 | ccc
(1 row)

這種場景下,就無法通過臟塊或解析死元組中的數據信息來恢復數據庫,下一篇介紹WALMINER恢復誤刪除的數據。

總結

如果不小心誤刪除了數據,可以通過特殊手段來恢復數據的,具體恢復步驟如下:

1. 對表執行禁用vacuum(特別強調,這一步非常重要)

ALTER TABLE t1 SET (autovacuum_enabled = false, toast.autovacuum_enabled = false);

2. 使用pg_dirtyread插件查詢被刪除的數據,同時將數據抽取到中間表

create table t1_bak select id ,name from ((SELECT * FROM pg_dirtyread('t1')
AS t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int, name text))) as foo;

另外,如何要找的數據己被vacuum,還可以通過分析數據具體被刪除的時間,然后通過WalMiner解析wal日志,找到對應的時間點,生成undo sql(如果執行的delete,undo sql就是insert語句)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207454.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207454.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207454.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【分享】我想上手機器學習

目錄 前言 一、理解機器學習 1.1 機器學習的目的 1.2 機器學習的模型 1.3 機器學習的數據 二、學習機器學習要學什么 2.1 學習機器學習的核心內容 2.2 怎么選擇模型 2.3 怎么獲取訓練數據 2.4 怎么訓練模型 三、機器學習的門檻 3.1 機器學習的第一道門檻 3.2 機器…

最新版IDEA專業版大學生申請免費許可證教學(無需學校教育郵箱+官方途徑+非破解手段)

文章目錄 前言1. 申請學籍在線驗證報告2. 進入IDEA官網進行認證3. 申請 JB (IDEA) 賬號4. 打開 IDEA 專業版總結 前言 當你進入本篇文章時, 你應該是已經遇到了 IDEA 社區版無法解決的問題, 或是想進一步體驗 IDEA 專業版的強大. 本文是一篇學生申請IDEA免費許可證的教學, 在學…

unity 2d 入門 飛翔小鳥 小鳥碰撞 及死亡(九)

1、給地面&#xff0c;柱體這種添加2d盒裝碰撞器&#xff0c;小鳥移動碰到就不會動了 2、修改小鳥的腳本&#xff08;腳本命名不規范&#xff0c;不要在意&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine;public class Fly : Mo…

kafka高吞吐、低延時、高性能的實現原理

作者&#xff1a;源碼時代-Raymon老師 Kafka的高吞吐、低延時、高性能的實現原理 Kafka是大數據領域無處不在的消息中間件&#xff0c;目前廣泛使用在企業內部的實時數據管道&#xff0c;并幫助企業構建自己的流計算應用程序。Kafka雖然是基于磁盤做的數據存儲&#xff0c;但…

可信固件-M (TF-M)

概述&#xff1a; 參考: Trusted Firmware-M Documentation — Trusted Firmware-M v2.0.0 documentation 開源代碼托管&#xff1a; trusted-firmware-m.git - Trusted Firmware for M profile Arm CPUs STM32 U5支持TF-M : STM32U5 — Trusted Firmware-M v2.0.0 document…

Meta Platforms推出Imagine:基于Emu的免費AI文本到圖像生成器服務

Meta Platform是Facebook、Instagram 和 WhatsApp 的母公司&#xff0c;也是領先的開源AI人工智能大語言模型 Llama 2的創建者。Meta Platforms 推出了一個名為 Imagine 的獨立文本到圖像 AI 生成器服務。Imagine 是基于 Meta 自己的 AI 模型 Emu 構建的&#xff0c;Emu 是在11…

循環結構中 break、continue、return 和exit() 的區別

循環結構中 break、continue、return 和exit() 的區別 文章目錄 循環結構中 break、continue、return 和exit() 的區別一、break語句二、continue語句三、return 語句四、exit() 函數 說明&#xff1a;本文內容參考牟海軍 著《C語言進階&#xff1a; 重點、難點與疑點解析》&a…

HTML程序大全(1):簡易計算器

HTML代碼&#xff0c;主要創建了幾個按鈕。 <div class"container"><div class"output" id"output">0</div><button class"button" onclick"clearOutput()" id"clear">C</button>…

C#調用win10系統自帶軟鍵盤的方法

上次做了個筆記是關于調用windows系統自帶的觸摸鍵盤的方法&#xff1a;C#調用Windows系統自帶觸摸鍵盤的方法_c# 虛擬鍵盤-CSDN博客 除了調用觸摸鍵盤&#xff0c;我們也可以通過調用win10的自帶軟鍵盤作為輸入途徑。 方法很簡單。 1、添加using System.Diagnostics引用。 …

選自《洛谷深入淺出進階篇》——歐拉函數+歐拉定理+擴展歐拉定理

歐拉函數&#xff1a; 歐拉函數定義&#xff1a; 1~n中與n互質的數的個數。 比如 歐拉函數是積性函數&#xff1a;&#xff08;也就是&#xff09;當 n與m互質的時候&#xff1a; 由算術基本定理&#xff0c;我們可以設n&#xff0c;那么我們只要計算出的取值就能求出的取…

5組10個共50個音頻可視化效果PR音樂視頻制作模板

我們常常看到的圖形跟著音樂跳動&#xff0c;非常有節奏感&#xff0c;那這個是怎么做到的呢&#xff1f;5組10個共50個音頻可視化效果PR音樂視頻制作模板滿足你的制作需求。 PR音樂模板|10個音頻可視化視頻制作模板05 https://prmuban.com/36704.html 10個音頻可視化視頻制作…

linux下查看文件當下的所有文件的大小和查找大文件

要查詢一個文件夾下面所有文件的總大小&#xff0c;您可以使用 du 命令配合一些參數。如果您只關心總大小&#xff0c;而不是各個子文件夾或文件的大小&#xff0c;可以使用以下命令&#xff1a; du -sh /path/to/your/directory在這個命令中&#xff1a; du 是磁盤使用情況的…

設計師福利!免費實用的7款Figma插件,讓你的工作事半功倍!

如今&#xff0c;Figma已經成為主流的原型和數字設計軟件之一&#xff0c;許多UI設計師和設計團隊開始選擇使用Figma。隨著Figma的快速更新和迭代&#xff0c;Figma插件庫變得越來越豐富。如果使用得當&#xff0c;將有助于提高您的設計效率。本文將介紹7個工作中非常實用的Fig…

echarts詞云圖echarts-wordcloud使用方法

1、echarts5.0以下的版本使用 echarts-wordcloud 1.0 的詞云 1. 安裝 wordCloud 1.0 依賴包npm install echarts-wordcloud12. man.js 注入import echarts-wordcloud 2、echarts5.0及以上的下載 echarts-wordcloud 2.0 版本 注意&#xff1a;npm install echarts-wordcloud …

微軟發布Orca2,“調教式”教會小規模大語言模型如何推理!

我們都知道在大多數情況下&#xff0c;語言模型的體量和其推理能力之間存在著正相關的關系&#xff1a;模型越大&#xff0c;其處理復雜任務的能力往往越強。 然而&#xff0c;這并不意味著小型模型就永遠無法展現出色的推理性能。最近&#xff0c;奶茶發現了微軟的Orca2公開了…

自動化操作腳本

文章目錄 vbsopenCV pyautogui vbs SSH連接并執行指令操作 Dim WshShell Set WshShellWScript.CreateObject("WScript.Shell") WshShell.Run "cmd.exe" WScript.Sleep 1000 WshShell.SendKeys "ssh xcmg10.27.40.103" WshShell.SendKeys &qu…

xxl-job詳解

目錄 1、xxl-job介紹1.1 xxl-job的原理1.1.1 執行器的注冊和發現1.1.2 調度中心調用執行器 1.2 quartz和xxl-job對比 2、快速入門2.1 下載并啟動2.2 在調度中心新增定時任務2.3 任務運行模式(BEAN、GLUE)2.4 xxl-job的總結 3、后端專屬技術群 1、xxl-job介紹 ? xxl-job是一個…

Python源碼30:海龜畫圖turtle畫紫色的小熊

turtle模塊是一個Python的標準庫之一&#xff0c;它提供了一個基于Turtle graphics的繪圖庫。Turtle graphics是一種流行的繪圖方式&#xff0c;它通過控制一個小海龜在屏幕上移動來繪制圖形。 turtle模塊可以讓您輕松地創建和控制海龜圖形&#xff0c;從而幫助您學習Python編…

Qt12.8

使用手動連接&#xff0c;將登錄框中的取消按鈕使用qt4版本的連接到自定義的槽函數中&#xff0c;在自定義的槽函數中調用關閉函數 將登錄按鈕使用qt5版本的連接到自定義的槽函數中&#xff0c;在槽函數中判斷ui界面上輸入的賬號是否為"admin"&#xff0c;密碼是否為…

lv11 嵌入式開發 中斷控制器14

目錄 1 中斷控制器 ?編輯 2 Exynos4412下的中斷控制器 2.1 概述 2.2 特征 ?編輯 2.3 中斷狀態 2.4 中斷類型 2.5 中斷控制器GIC中斷表 3 中斷控制器寄存器詳解 3.1 ICDDCR&#xff08;Interrupt Controller Distributor Control Register&#xff09; 3.2 ICDISER…