使用者工具

網站工具


database:postgresql:数据块损坏的恢复

(转)PostgreSQL的恢复: (一) 数据块损坏的恢复

PostgreSQL的恢复: (一) 数据块损坏的恢复

歌思  info@redgres.com

http://www.redgres.com/web/node/17

   由于磁盘坏道或者是内存问题等硬件上的原因,有时候会导致数据库的数据文件的一些数据块的损坏,使得某些表不能正常访问,本文谈一下PostgreSQL数据块损坏时候,表数据的恢复方法。

   PostgreSQL采用一个表存放在一个或者多个物理文件,所以数据块的损坏一般只会影响到一个表,使得该表的数据不能查询或者是备份,下面是一个常见的异常的例子:

# select * from test ;

ERROR:  invalid page header in block 1 of relation base/34780/34781


这个错误是说数据所在的目录下面base子目录,oid为34780的数据库,表的文件id为34781的表(即上述例子的test)的第一页(注意是从0页开始)数据块的头出现了错误,所以数据库不能访问。



数据块的损坏的情形比较复杂,所以如何恢复,或者是能恢复到什么情形不能一概而论。最好的情况是丢失一个数据块里面的所有记录(也有可能只丢失某些记录,但是方法比较复杂),最坏也有可能整个表丢失。PostgreSQL没有提供像Oracle那样的文件恢复或者是块修复的功能,但也有一些方法可以修复表,这里简单讨论一下一个数据块损坏的情况下,如何恢复。



最简单的方法是,用备份恢复!如果你有做备份和日志归档,则出现问题以后,恢复到最新即可。如果没有备份,则请参考下面的方法。



重要:在做下面的操作前,先把数据库的数据文件的目录先备份!!!!!



方法1 利用参数zero_damaged_pages



PostgreSQL提供了一个隐藏参数zero_damaged_pages, 当这个参数为true的时候,会忽略所有数据有损坏的页面。设置的方法为:打开postgresql.conf文件,在文件的添加一个参数zero_damaged_pages = true, 重起PostgreSQL。



设置完后,当访问表的时候,会提示说已经忽略损坏的页面:

# select count(*) from test ;

WARNING:  invalid page header in block 1 of relation base/34780/34781; zeroing out page

count

-------

   760

(1 row)




该表原有1000条记录,由于一个页面损坏,丢失了240条记录。表可以访问以后,可以把表dump下来,或者是select到另外一张临时表,然后把原来的表删除掉重建。当然如果有其他外部约束的话,相关的表和索引也要处理,这里不详细讨论。



这种方法不会对物理文件作修改,只是把内存上,损坏页面的缓存变为0。



方法2 手动清除损坏的页面



在某些情形下,zero_damaged_pages可能不一定有些,这时可以尝试手动把坏的页面清除。

根据错误提示 ERROR:  invalid page header in block 1 of relation base/34780/34781 我们可以找到相应的文件, 文件的路径为: 数据目录/base/34780/34781,只要用工具手动把上面提示的坏块清除即可。在Linux下面可以用dd工具把相应的页面清除:



$dd if=/dev/zero of=/home/postgres/data/base/34780/42995 bs=8192 seek=1 count=1 conv=notrunc




清除完后,查询表即可正常访问。



# select count(*) from test ;

count

-------

   760

(1 row)






上面简单讨论了一下数据块损坏的表的恢复方法。由于这些方法都是有一定的局限性,而且丢失数据的数据量也不是完全确定,所以平时一定要做好备份工作。

http://www.redgres.com/web/node/17

--

歌思-- PostgreSQL专家 --info@redgres.com

PostgreSQL invalid page header in block xxxx of relation base xxxx

PostgreSQL invalid page header in block xxxx of relation base xxxx
有時遇到table 壞軌,要救回資料可以照以下方式來作
reindex db發生error:

database "prod" failed: ERROR: invalid page header in block 6066 of relation base/16384/25370

依照數字可以找出database跟object
select oid,* from pg_database where oid::varchar='16384';
select oid,* from pg_class where oid::varchar='16384';

修復方法:reindex database 或 table
整個DB reindex:
reindexdb -U postgres -a
單一table Reindex:
psql -U postgres -c "reindex table customers"


ps.若是reindex時還是有大量的error,則在postgresql.conf裏最後一行加上zero_damaged_pages = on,並重啟postgresql database


zero_damaged_pages 說明:(8.0以後的postgresql支援)

Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current command. Setting zero_damaged_pages to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page. But it allows you to get past the error and retriev
database/postgresql/数据块损坏的恢复.txt · 上一次變更: 2011/05/25 11:10 (外部編輯)