今天早上發生了一件事,業務人員一不小心刪除了某張表的資料。說實話大哥我玩兒pg也不久,很多運維經驗也是邊踩坑邊總結,所以在誤刪除恢復這件事上哥的經驗還是比較匱乏的。而且還有一件比較可怕的事情是該資料庫的物理備份還沒有弄好。
現實**打臉,只怪自己學藝不深。研究一通之後發現並不是外掛程式問題。以下是在測試庫上使用外掛程式的過程。使用了中的demo。
postgres=# create table foo (bar bigint, baz text);
create table
postgres=# insert into foo values (1, 'test'), (2, 'new test');
insert 0 2
postgres=# delete from foo where bar = 1;
delete 1
postgres=# select * from foo;
bar | baz
2 | new test
(1 row)
postgres=# select * from pg_dirtyread('foo')
postgres-# as t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,
postgres(# bar bigint, baz text);
tableoid | ctid | xmin | xmax | cmin | cmax | dead | bar | baz
2784670 | (0,1) | 17635311 | 17635312 | 0 | 0 | t | 1 | test
2784670 | (0,2) | 17635311 | 0 | 0 | 0 | f | 2 | new test
從測試庫上可以清楚的看到,dead為true的死元組資料可以通過pg_dirtyread外掛程式查到,但是我們生產為什麼查不到呢?
在生產庫根本就查不到dead為true的元組資料。這說明系統程序autovacuumed已經執行了清理。
對於這種情況,在oracle中就只能基於時間點的恢復和挖掘redolog了。而pg挖掘wal日誌的方法網上又搜了一通,發現可以使用瀚高公司的walminer外掛程式。
#majorversion支援『9.5』,『9.6』,『10』,『11』,『12』,『13』
use_pgxs=1 majorversion=12 make install
postgres=# create extension walminer;
create extension
安裝完成之後需要先載入wal日誌,這裡你可以選擇全部載入,也可以選擇出故障時間點的日誌進行載入。載入完可以列出載入的日誌資訊。
postgres=# select walminer_wal_add('pg_wal');
walminer_wal_add
64 file add success
(1 row)
postgres=# select walminer_wal_list();
walminer_wal_list
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000023)
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000024)
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000025)
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000026)
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000027)
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000028)
(/pg_data1/pg12/pgdata/pg_wal/000000010000024e00000029)
接下來執行walminer_all()就可以解析新增的全部wal日誌,然後檢視walminer_contents表就可以看到之前執行的sql記錄了,包括反向的undosql都已經生成好了。
postgres=# select walminer_all();
notice: switch wal to 000000010000024d000000f6 on time 2020-10-26 16:32:34.782724+08
notice: con not find relfilenode 2777602 in dictionary, ignored related records
notice: switch wal to 000000010000024d000000f7 on time 2020-10-26 16:32:34.87947+08
walminer_all
pg_minerwal success
(1 row)
postgres=# select * from walminer_contents;
sqlno | xid | topxid | sqlkind | minerd | timestamp | op_text | undo_text | complete | sch
ema | relation | start_lsn | commit_lsn
1 | 17635311 | 0 | 1 | t | 2020-10-26 16:31:42.373436+08 | insert into public.foo(bar ,baz) values(1 ,'test') | delete from public.foo where bar=1 and baz='test' | t | pub
lic | foo | 24d/f7cfcb70 | 24d/f7cfcc30
2 | 17635311 | 0 | 1 | t | 2020-10-26 16:31:42.373436+08 | insert into public.foo(bar ,baz) values(2 ,'new test') | delete from public.foo where bar=2 and baz='new test' | t | pub
lic | foo | 24d/f7cfcbb8 | 24d/f7cfcc30
1 | 17635312 | 0 | 3 | t | 2020-10-26 16:31:45.936969+08 | delete from public.foo where bar=1 and baz='test' | insert into public.foo(bar ,baz) values(1 ,'test') | t | pub
lic | foo | 24d/f7cfcc30 | 24d/f7cfcc98
(3 rows)
這裡操作方法和oracle中的logminger類似。具體可以參考redeme。
對於今天早上出現的這類問題,比較鬧心的一點是經驗不足,很多東西都要現學現查。如果能夠提前部署好這些外掛程式,並在最短的時間做出選擇,就能快速的恢復資料。同時當前生產庫也沒有部署備份,無法從備份基於時間點的恢復。因此,對我們來說,pg運維仍然任重而道遠,這裡給大家分享出來,也是為了小夥伴們少走彎路。
參考文獻
pg_dirtyread
walminer2.0beta功能改進說明
Oracle中恢復某張表丟失資料的方法
oracle中恢復某張表丟失資料的方法 2010 05 15 16 55 利用oracle資料庫的scn進行恢復,oracle資料庫每隔5分鐘,系統會產生乙個系統時間標記與scn的匹配並存入sys.smon scn time表中。我們對這個備份機制做如下測試 查詢出來資料 select t.t.ro...
mysql匯出匯入某張表
一般表資料少的話都用圖形介面了,看著比較方便。如果表中資料比較多,用圖形介面極容易卡死,這個時候就要用到命令列了。用命令列匯出匯入大量資料還是比較快的,方法如下 匯出庫db1中的表table1 usr bin mysqldump uroot proot default character set u...
Oracle設定某張表為唯讀
oracle 11g開始支援設定某張表為唯讀,這樣可以防範對某些表的修改,起到一定的安全性。設定如下 設定表為唯讀許可權 加鎖 alter table tab name read only 設定表的讀寫許可權 解鎖 alter table tab name read write 當表需要進行更新 增...