1. 程式人生 > 其它 >postgresql-模擬丟失資料檔案模擬測試

postgresql-模擬丟失資料檔案模擬測試

postgresql-模擬丟失資料檔案模擬測試

目錄

環境準備

--建立測試表
postgres=# create table test (n_bh int4 primary key,c_name varchar(300));
CREATE TABLE
Time: 1162.555 ms
--插入資料
postgres=# insert into test select generate_series(1,100000),'zhangsan';
INSERT 0 100000
Time: 2181.978 ms
--檢視檔案路徑
postgres=# select pg_relation_filepath('test');
 pg_relation_filepath 
----------------------
 base/13287/3983070
(1 row)

Time: 0.611 ms
--檢視索引
postgres=# select schemaname,tablename,indexname,indexdef from pg_indexes where tablename = 'test';
 schemaname | tablename | indexname |                            indexdef                           
  
------------+-----------+-----------+---------------------------------------------------------------
--
 public     | test      | test_pkey | CREATE UNIQUE INDEX test_pkey ON public.test USING btree (n_bh
)
(1 row)

Time: 2.076 ms

--檢視索引路徑
postgres=# select pg_relation_filepath('test_pkey');
 pg_relation_filepath 
----------------------
 base/13287/3983073
(1 row)

Time: 0.655 ms

--檢視所對應檔案
[root@sqlfx 13287]# ll
total 13987
...
-rw-------. 1 thunisoft thunisoft 4431872 Oct 21 15:38 3983070
-rw-------. 1 thunisoft thunisoft   24576 Oct 21 15:38 3983070_fsm
-rw-------. 1 thunisoft thunisoft 2260992 Oct 21 15:38 3983073
to

還有vm沒有,如果是無日誌表可能還有init檔案

索引檔案丟失

--1.索引檔案丟失
[thunisoft@sqlfx 13287]$ touch 3983073bak
[thunisoft@sqlfx 13287]$ mv 3983073 3983073bak
[thunisoft@sqlfx 13287]$ ll

-rw-------. 1 thunisoft thunisoft 4431872 Oct 21 15:41 3983070
-rw-------. 1 thunisoft thunisoft   24576 Oct 21 15:38 3983070_fsm
-rw-------. 1 thunisoft thunisoft 2260992 Oct 21 15:41 3983073bak

--2.刪除索引檔案後在沒有重啟資料庫前還是可以訪問的,這應該是從快取獲取的
postgres=# select pg_relation_filepath('test_pkey');
 pg_relation_filepath 
----------------------
 base/13287/3983073
(1 row)

Time: 0.655 ms
--3.插入一條資料
postgres=# insert into test values(200000,'lisi');
INSERT 0 1
Time: 253.284 ms
--4.也能夠訪問
postgres=# select * from test where n_bh = 200000;
  n_bh  | c_name 
--------+--------
 200000 | lisi
(1 row)

Time: 0.803 ms

--5.查詢也可以正常走索引
postgres=# explain analyze select * from test where n_bh = 200000;
                                                    QUERY PLAN                                      
              
----------------------------------------------------------------------------------------------------
--------------
 Index Scan using test_pkey on test  (cost=0.28..8.30 rows=1 width=520) (actual time=0.019..0.019 ro
ws=1 loops=1)
   Index Cond: (n_bh = 200000)
 Planning Time: 0.133 ms
 Execution Time: 0.095 ms
(4 rows)

Time: 0.873 ms

--6.但是在執行checkpint的時候就會失敗
postgres=# checkpoint;
錯誤:  檢查點請求失敗
HINT:  詳細資訊請參考伺服器日誌.
Time: 301.294 ms
--7.這個時候查詢仍然可以走索引
postgres=# explain analyze select * from test where n_bh = 1;
                                                    QUERY PLAN                                      
              
----------------------------------------------------------------------------------------------------
 Index Scan using test_pkey on test  (cost=0.28..8.30 rows=1 width=520) (actual time=0.022..0.023 ro
ws=1 loops=1)
   Index Cond: (n_bh = 1)
 Planning Time: 0.150 ms
 Execution Time: 0.105 ms
(4 rows)

Time: 0.998 ms
--8.檢視資料庫日誌報錯,日誌檔案中大量的報錯
錯誤	58P01	無法開啟檔案 "base/13287/3983073": 沒有那個檔案或目錄		寫入關係base/13287/3983073的塊275			
警告	58030	無法寫入base/13287/3983073的塊275	多次失敗 --- 寫錯誤可能是永久性的
--9.關閉資料庫
background worker "logical replication launcher" (PID 23073) 已退出, 退出程式碼 1
正在關閉
無法開啟檔案 "base/13287/3983073": 沒有那個檔案或目錄
無法寫入base/13287/3983073的塊275
檢查點(checkpointer)程序 (PID 23068) 已退出, 退出程式碼 1
中斷任何其它已啟用的伺服器程序
歸檔程序 (PID 23071) 已退出, 退出程式碼 1
資料庫系統異常關閉
資料庫系統已關閉
--10.重啟資料庫後訪問
postgres=# select * from test where n_bh = 200000;
錯誤:  索引"test_pkey"在塊0上包含未期望的零頁
HINT:  請重建索引 (REINDEX).
--11.重建索引後可以繼續訪問
postgres=# reindex index test_pkey;
REINDEX
postgres=# select * from test where n_bh = 200000;
  n_bh  | c_name 
--------+--------
 200000 | lisi
(1 row)

索引檔案丟失,由於資料檔案存在可以重建,所以問題不大

fsm檔案丟失

[thunisoft@sqlfx 13287]$ touch 3983070_fsmbak 
[thunisoft@sqlfx 13287]$ mv 3983070_fsm  3983070_fsmbak
重啟資料庫後fsm檔案又會重新生成

mv檔案丟失

postgres=# update test set c_name ='lisi' where n_bh > 10000;
UPDATE 90001
postgres=# vacuum test;
VACUUM
[thunisoft@sqlfx 13287]$ ll
total 24840
...
-rw-------. 1 thunisoft thunisoft 8421376 Oct 21 16:04 3983070
-rw-------. 1 thunisoft thunisoft   24576 Oct 21 16:01 3983070_fsmbak
-rw-------. 1 thunisoft thunisoft    8192 Oct 21 16:08 3983070_vm
-rw-------. 1 thunisoft thunisoft 2260992 Oct 21 15:41 3983073bak
-rw-------. 1 thunisoft thunisoft 6307840 Oct 21 16:04 3991251

[thunisoft@sqlfx 13287]$ touch 3983070_vm_bak
[thunisoft@sqlfx 13287]$ mv 3983070_vm  3983070_vm_bak
[thunisoft@sqlfx 13287]$ ll
...
-rw-------. 1 thunisoft thunisoft 8421376 Oct 21 16:10 3983070
-rw-------. 1 thunisoft thunisoft   24576 Oct 21 16:10 3983070_fsm
-rw-------. 1 thunisoft thunisoft   24576 Oct 21 16:01 3983070_fsmbak
-rw-------. 1 thunisoft thunisoft    8192 Oct 21 16:10 3983070_vm_bak
-rw-------. 1 thunisoft thunisoft 2260992 Oct 21 15:41 3983073bak

重啟後vm也正常生成了

資料檔案丟失

--模擬資料丟失
[thunisoft@sqlfx 13287]$ touch 3983070bak
[thunisoft@sqlfx 13287]$ mv 3983070 3983070bak
--執行查詢
postgres=# select * from test limit 10;
致命錯誤:  由於管理員命令中斷聯接
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
--再次執行
postgres=# select * from test limit 10;
錯誤:  無法開啟檔案 "base/13287/3983070": 沒有那個檔案或目錄
--pg_class中還能查到
postgres=# select oid,relname from pg_class where relname = 'test';
   oid   | relname 
---------+---------
 3983070 | test
(1 row)

--可以看到直接刪除檔案,還沒有清理
postgres=# select relid,relname,last_vacuum,last_autovacuum,last_analyze,last_autoanalyze from pg_stat_all_tables where relname= 'test';
  relid  | relname | last_vacuum | last_autovacuum | last_analyze | last_autoanalyze 
---------+---------+-------------+-----------------+--------------+------------------
 3983070 | test    |             |                 |              | 
(1 row)
--嘗試重啟試試
postgres=# select oid,relname from pg_class where relname = 'test';
   oid   | relname 
---------+---------
 3983070 | test
(1 row)

postgres=# select relid,relname,last_vacuum,last_autovacuum,last_analyze,last_autoanalyze from pg_stat_all_tables where relname= 'test';
  relid  | relname | last_vacuum | last_autovacuum | last_analyze | last_autoanalyze 
---------+---------+-------------+-----------------+--------------+------------------
 3983070 | test    |             |                 |              | 
(1 row)

postgres=# select schemaname,tablename,indexname,indexdef from pg_indexes where tablename = 'test';
 schemaname | tablename | indexname |                            indexdef                           
  
------------+-----------+-----------+---------------------------------------------------------------
--
 public     | test      | test_pkey | CREATE UNIQUE INDEX test_pkey ON public.test USING btree (n_bh
)
(1 row)

--表字段
postgres=# select attname,atttypid  from pg_attribute where attrelid = '3983070';
 attname  | atttypid 
----------+----------
 tableoid |       26
 cmax     |       29
 xmax     |       28
 cmin     |       29
 xmin     |       28
 ctid     |       27
 n_bh     |       23
 c_name   |     1043
(8 rows)


postgres=# select * from test limit 10;
錯誤:  無法開啟檔案 "base/13287/3983070": 沒有那個檔案或目錄

索引檔案也還在,表的定義也還在,但是檔案丟失了

單個表文件丟失,不會影響資料庫啟動,但是訪問表的時候就會出現問題,這種物理刪除檔案是沒法恢復的,不會記錄日誌,只能做好備份

pg_wal日誌丟失

--丟失wal,啟動資料庫報錯
日誌	0	資料庫上次關閉時間為 2019-10-28 04:06:35 EDT		
日誌	0	正在建立丟失的WAL目錄"pg_wal/archive_status"		
日誌	0	無效的主 checkpoint 記錄		
比致命錯誤還過分的錯誤	XX000	無法找到一個有效的 checkpoint 記錄		
致命錯誤	57P03	資料庫系統啟動中	

XX000:內部錯誤(INTERNAL ERROR) 

--重置資料檔案:
[thunisoft@sqlfx bin]$ ./pg_resetwal -f /home/thunisoft/abdata/6.0/abase1
Write-ahead log reset
--重置後資料庫可以正常啟動
--可以看到還原了最後一個wal日誌檔案
[thunisoft@sqlfx bin]$ cd /home/thunisoft/abdata/6.0/abase1/pg_wal
[thunisoft@sqlfx pg_wal]$ ll
total 16384
-rw-------. 1 thunisoft thunisoft 16777216 Oct 28 16:33 000000010000001500000063
drwx------. 2 thunisoft thunisoft        6 Oct 28 16:06 archive_status
[thunisoft@sqlfx pg_wal]$ 

刪除所有wal檔案,然後正常停止(fast模式)資料庫,再啟動資料庫發現開始插入的資料還在(說明正常停止的時候資料從快取中寫入了磁碟)
如果是kill掉程序(Immediate模式)那麼開始插入的資料實際上是沒有寫入資料檔案的,再次啟動的時候找不到wal日誌恢復,所以會丟失這部分資料

--刪除控制檔案後,要先啟動才能生成pg_wal/archive_status,不然直接執行pg-resetwal會直接報錯:
pg_resetwal: could not open directory "pg_wal/archive_status": No such file or directory

如果缺失wal檔案,啟動資料庫會和以前缺少license一樣一直生成core.xx這樣的core檔案,大小和shared_buffers一樣大。

pg_xact日誌丟失

--先關閉資料庫,然後刪除pg_xact日誌,再啟動資料庫
--如果正常關閉資料庫會生成一個pg_xact日誌,可以kill一個數據庫,然後刪掉就能復現
資料庫上次關閉時間為 2019-10-28 06:07:59 EDT		
無法處理事物 12207234 的狀態	無法開啟檔案 "pg_xact/000B": 沒有那個檔案或目錄	
啟動程序 (PID 32291) 已退出, 退出程式碼 1		
由於啟動程序失敗, 終止啟動		
資料庫系統已關閉
--將開始的備份檔案000B還原到pg_xact下面,可以啟動資料庫,但是在建表的時候報錯了
--建立資料庫會報錯檔案不存在,但是在postgres資料庫下面是可以建立的
abase=# create table test1(c_bh varchar(300), primary key(c_bh));
錯誤:  無法處理事物 11002481 的狀態
DETAIL:  無法開啟檔案 "pg_xact/000A": 沒有那個檔案或目錄
abase=# \q

--新建檔案,確保建立的檔案有許可權
[thunisoft@sqlfx pg_xact]$ dd if=/dev/zero of=/home/thunisoft/abdata/6.0/abase1/pg_xact/000A bs=256k count=1
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.000834625 s, 314 MB/s

--建立表成功
abase=# create table test1(c_bh varchar(300), primary key(c_bh));
CREATE TABLE

當然這樣並不能完全保證所有表都沒有問題,最好的做法是將資料庫做一個備份,然後重新還原,找到問題表
刪除一些表的時候報錯:
db_imp=# drop table db_xfzx.t_zfxx;
錯誤:  試圖刪除不可見元組
db_imp=# truncate db_xfzx.t_zfxx;
錯誤:  unexpected chunk number 1 (expected 0) for toast value 3172498 in pg_toast_2619
--執行vacuum full後還是報錯
db_imp=# vacuum full db_xfzx.t_zfxx;
VACUUM
db_imp=# vacuum (analyze,verbose) db_xfzx.t_zfxx;
資訊:  正在清理 (vacuum)  "db_xfzx.t_zfxx"
資訊:  索引"t_zfxx_pkey"在7609個頁中包含了行版本號1055308
......
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
資訊:  "pg_toast_3172473": 在超出0頁的0中找到可刪除版本號0, 不可刪除的版本號0
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 12207554
有0個未用的項指標。
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 個頁面完全為空。
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
資訊:  正在分析 "db_xfzx.t_zfxx"
資訊:  "t_zfxx": 已經掃描了59417頁的30000, 包含532769可用的記錄和0不能用的記錄; 在示例中有30000條記錄,估算所有記錄為1055185 .
錯誤:  unexpected chunk number 1 (expected 0) for toast value 3172498 in pg_toast_2619
--重建整個表的索引
db_imp=# reindex table db_xfzx.t_zfxx;
--還是報一樣的錯
db_imp=# select count(*) from db_xfzx.t_zfxx;
錯誤:  missing chunk number 1 for toast value 3172503 in pg_toast_2619

--檢視t_zfxx表的toast發現是pg_toast_3172473,並不是pg_toast_2619
db_imp=# select reltoastrelid::regclass from pg_class where relname = 't_zfxx';
       reltoastrelid       
---------------------------
 pg_toast.pg_toast_3172473
(1 row)

db_imp=# select relname,relfilenode,reltoastrelid from pg_class where relname='t_zfxx';
 relname | relfilenode | reltoastrelid 
---------+-------------+---------------
 t_zfxx  |     4532733 |       3172476
(1 row)

--原來pg_toast_2619對應的表是pg_statistic,是統計資訊表的toast丟失了
db_imp=# select reltoastrelid::regclass,relname from pg_class;
       reltoastrelid       |                    relname                    
---------------------------+-----------------------------------------------
 -                         | i_t_zfxx_c_zybz
 -                         | i_t_zfxx_c_zyjq
 pg_toast.pg_toast_3172473 | t_zfxx
 pg_toast.pg_toast_2619    | pg_statistic
--再次嘗試vacuum full,發現還缺少pg_xact
db_imp=# vacuum (analyze,verbose) pg_statistic;
資訊:  正在清理 (vacuum)  "pg_catalog.pg_statistic"
錯誤:  無法處理事物 595 的狀態
DETAIL:  無法開啟檔案 "pg_xact/0000": 沒有那個檔案或目錄
db_imp=# vacuum full pg_statistic;
錯誤:  無法處理事物 595 的狀態
DETAIL:  無法開啟檔案 "pg_xact/0000": 沒有那個檔案或目錄

--不如做一次全的pg_dump看看缺少那些
[thunisoft@sqlfx bin]$ ./pg_dumpall -Usa -p 6543  -f /home/thunisoft/pg_dumpall.dump
pg_dump: [archiver (db)] query failed: 錯誤:  無法處理事物 582 的狀態
LINE 1: SELECT pg_catalog.pg_is_in_recovery()
               ^
DETAIL:  無法開啟檔案 "pg_xact/0000": 沒有那個檔案或目錄
pg_dump: [archiver (db)] query was: SELECT pg_catalog.pg_is_in_recovery()
pg_dumpall: pg_dump failed on database "template1", exiting

pg_dump: [archiver (db)] query failed: 錯誤:  無法處理事物 10445722 的狀態
DETAIL:  無法開啟檔案 "pg_xact/0009": 沒有那個檔案或目錄

在備份過程中報了許多不存在的pg_xact

--建立缺失的檔案
[thunisoft@sqlfx pg_xact]$ dd if=/dev/zero of=/home/thunisoft/abdata/6.0/abase1/pg_xact/0000 bs=256k count=1
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.000790407 s, 332 MB/s
[thunisoft@sqlfx pg_xact]$ dd if=/dev/zero of=/home/thunisoft/abdata/6.0/abase1/pg_xact/0009 bs=256k count=1
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.00077558 s, 338 MB/s
[thunisoft@sqlfx pg_xact]$ dd if=/dev/zero of=/home/thunisoft/abdata/6.0/abase1/pg_xact/0006 bs=256k count=1
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.000763672 s, 343 MB/s
[thunisoft@sqlfx pg_xact]$ dd if=/dev/zero of=/home/thunisoft/abdata/6.0/abase1/pg_xact/0007 bs=256k count=1
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.000707374 s, 371 MB/s
[thunisoft@sqlfx pg_xact]$ dd if=/dev/zero of=/home/thunisoft/abdata/6.0/abase1/pg_xact/0008 bs=256k count=1
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.000749594 s, 350 MB/s
--在嘗試vacuum full pg_statistic和t_zfxx
db_imp=# vacuum full pg_statistic;
錯誤:  uncommitted xmin 11359036 from before xid cutoff 12207600 needs to be frozen

目前還是報錯,那麼現在有兩個方案,一是處理上面的報錯,二是還原備份出來的資料。先嚐試處理上面的錯誤。

另外能不能重啟資料庫讓資料庫自動解決這個問題呢?試了下,重啟之後還是報上面的錯誤,沒能解決

--重啟後:
db_imp=# vacuum full pg_statistic;
錯誤:  uncommitted xmin 11359036 from before xid cutoff 12207644 needs to be frozen
db_imp=# reindex table  pg_statistic;
REINDEX
db_imp=# vacuum freeze pg_statistic;
錯誤:  uncommitted xmin 11359036 from before xid cutoff 12207711 needs to be frozen
--t_zfxx表只能插入不能查詢,
db_imp=# select count(*) from db_xfzx.t_zfxx;
錯誤:  missing chunk number 0 for toast value 3172504 in pg_toast_2619
db_imp=# select c_bh from db_xfzx.t_zfxx where c_bh = '123';
錯誤:  missing chunk number 0 for toast value 3172498 in pg_toast_2619
db_imp=# insert into db_xfzx.t_zfxx(c_bh) values('123');
INSERT 0 1
db_imp=# select c_bh from db_xfzx.t_zfxx where c_bh = '123';
錯誤:  missing chunk number 0 for toast value 3172498 in pg_toast_2619
db_imp=# 
db_imp=# explain select c_bh from db_xfzx.t_zfxx where c_bh = '123';
錯誤:  missing chunk number 0 for toast value 3172498 in pg_toast_2619
db_imp=# select c_bh from db_xfzx.t_zfxx limit 1;
錯誤:  missing chunk number 0 for toast value 3172498 in pg_toast_2619
--pg_statistic可以查詢所有,但是不能vacuum full
db_imp=# select starelid  from pg_statistic limit 1;
 starelid 
----------
     1260
(1 row)

db_imp=# select count(*) from pg_statistic;
 count 
-------
   411
(1 row)

db_imp=# vacuum full pg_statistic;
錯誤:  uncommitted xmin 11359036 from before xid cutoff 12207714 needs to be frozen

嘗試跳過錯誤的行,繼續vacuum full

--zero_damaged_pages:意思是說當系統檢測到磁碟頁損壞,並導致postgresql資料取消當前的事務並提交一份錯誤報告資訊。這個引數是bool型別的,預設是off,意思是系統遇到這類因磁碟、記憶體等硬體引起的問題就會給出這樣一份錯誤提示,當我們設定為on時,就可以忽略這些錯誤報告,並擦除掉這些損壞的資料,沒受影響的資料還是正常的。 
--這個引數有一個嚴重的壞處,就是會擦除到那些被損壞的資料,好處也有,你可以忽略掉那些錯誤資訊,掃描時跨過那些錯誤塊,使資料庫能正常使用。所以為了資料完整性考慮是不建議開啟這個引數的,只有當你的資料庫真的打不開、宕機了,沒有其他希望恢復資料庫的時候再去使用這個引數。 我們是在回收大資料的時候出現的如下故障: 
db_imp=# alter system set zero_damaged_pages=on;
ALTER SYSTEM
db_imp=# select pg_relaod_conf();
--仍然報錯
db_imp=# vacuum freeze pg_statistic;
錯誤:  uncommitted xmin 11359036 from before xid cutoff 12207711 needs to be frozen

zero_damaged_pages:這個引數一般處理這個報錯:

invalid page header in block 59640 of relation base/175812/1077620; zeroing out page

如果pg_xact丟失導致系統表資料出現異常,最後只能靠pg_dumpall出來的資料然後還原。

pg_authid系統表資料丟失

pg_authid的使用者資訊被刪除以後,資料庫如果退出登入後,再登入就登入不了。
[thunisoft@sqlfx bin]$ psql -Usa postgres
psql: 致命錯誤:  角色 "sa" 不存在
--插入資料
[SQL]INSERT INTO pg_authid VALUES ('sa', 't', 't', 't', 't', 't', 't', 't', '-1', 'f', '0', '9', 'md53072dd49bbf18c5cbaae66711066bf14', NULL);
[Err] 錯誤:  permission denied for table pg_authid

嘗試使用單使用者模式

--單使用者啟動
[thunisoft@sqlfx bin]$ ./postgres --single -D /home/thunisoft/abdata/6.0/abase1/ postgres
2019-10-30 03:26:57.877 EDT -  -  -  - 29124: 警告:  當前資料庫系統中沒有定義角色
2019-10-30 03:26:57.877 EDT -  -  -  - 29124: 提示:  您應該立即執行 CREATE USER "thunisoft" SUPERUSER;.

PostgreSQL stand-alone backend 11.1
--根據提示建立超級使用者
backend> create user "sa" superuser;
2019-10-30 03:27:39.243 EDT -  -  -  - 29124: 錯誤:  can not assign to superuser!
2019-10-30 03:27:39.243 EDT -  -  -  - 29124: 語句:  create user "sa" superuser;
--建立超級使用者報錯,但是可以建立普通的sa使用者
backend> create user sa password 'tusc@6789#JKL';

--退出單使用者
輸入 EOF(Control+D)即可退出會話。如果你已經使用了 -j 則必須連續使用兩個 EOF 才行。

使用單使用者建立普通使用者後,可以登陸,但是不能建立超級管理員

在abase6.0中如果刪除了超級管理員就加不上了,這是因為abase6.0做了限制,這點我一開始也忽略了,除了abase6.0,其他版本都可以重新建立超級管理員,(如果在使用abase6.0,建議升級到abase6.0.1)

abase3.6.1測試:

--先備份pg_authid
[thunisoft@sqlfx ~]$ pg_dump -Usa -d postgres -t pg_authid -p 7543 -f /home/thunisoft/pg_authid36.dump
[thunisoft@sqlfx ~]$ psql -Usa -d postgres -p 7543 
psql (11.1, server 9.6.4)
Type "help" for help.
--系統表不能被刪除
postgres=# drop table pg_authid;
ERROR:  permission denied: "pg_authid" is a system catalog
--刪除表資料
postgres=# delete from pg_authid;
DELETE 2
postgres=# select * from pg_authid;
 rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | r
olpassword | rolvaliduntil 
---------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+--
-----------+---------------
(0 rows)
postgres=# \q
--連線失敗
[thunisoft@sqlfx ~]$ psql -Usa -d postgres -p 7543 
psql: FATAL:  role "sa" does not exist
--刪除了使用者,psql還原也會失敗
[thunisoft@sqlfx ~]$ psql -Usa -d postgres -p 7543 -f /home/thunisoft/pg_authid36.dump 
psql: FATAL:  role "sa" does not exist

--如果像navicat沒有退出,那麼連線還在,如果退出了,sa就連不上了
--考慮先用單使用者模式建立一個使用者
[thunisoft@sqlfx bin]$ ./postgres --single -D /opt/thunisoft/abdata/3.6/abase1/ postgres
2019-11-01 15:08:46.144 CST -  -  -  - 17854: WARNING:  no roles are defined in this database system
2019-11-01 15:08:46.144 CST -  -  -  - 17854: HINT:  You should immediately run CREATE USER "thunisoft" SUPERUSER;.

PostgreSQL stand-alone backend 9.6.4
backend> create user thunisoft superuser password '123456';
backend> create user sa1 superuser password '123456';

這樣建立了兩個使用者thunisoft和sa1然後嘗試還原備份的表
[thunisoft@sqlfx bin]$ psql -Usa1 -d postgres -p 7543 -f /home/thunisoft/pg_authid36.dump 
SET
COPY 2

--資料還原
[thunisoft@sqlfx bin]$ psql -Usa1 postgres -p 7543
psql (11.1, server 9.6.4)
Type "help" for help.
postgres=# select rolname,rolsuper from pg_authid;
      rolname      | rolsuper 
-------------------+----------
 thunisot          | f
 thunisoft         | t
 sa1               | t
 pg_signal_backend | f
 sa                | t
(5 rows)
--abase5.0以上可以使用ab_repair再資料庫還沒有做自動清理前來恢復刪除的資料
--abase6.0有安全開關misopt_preventing不允許全表的刪除
當然還有一些野路子就是修改資料檔案,但是修改資料檔案後需要重建索引,因為索引檔案不會自動修改。

總結

1.索引檔案丟失或者損壞,可以靠重建索引恢復

2.fsm以及mv檔案的丟失,重啟資料庫會自動恢復

3.單個表文件丟失,不會影響資料庫啟動,但是訪問表的時候就會出現問題,這種物理刪除檔案是沒法恢復的,不會記錄日誌,只能做好備份

4.pg_wal和pg_xact日誌丟失可以恢復,但是可能會丟失部分資料

5.系統表pg_authid資料丟失後可以重新建立超級管理員,依靠備份恢復

6.最近發生多起數誤刪資料的問題,都是由於操作不當造成,生產環境在做操作前最好做好備份,檢查所執行的指令碼沒有問題再操作。