Postgres ctid以阻止计数不匹配

问题描述 投票:0回答:1

我正在使用Postgres 9.4.5,但在其中一张表中检测到损坏。在特定表上运行查询时,我注意到了这一点,导致整个数据库进入恢复模式。症状与本文中发现的症状一致:

https://www.endpoint.com/blog/2010/06/01/tracking-down-database-corruption-with

我尝试按照以下步骤将损坏的块清零,但按照以下步骤操作,我的ctid为507578。

database=# \set FETCH_COUNT 1
database=# \pset pager off
Pager usage is off.
database=# SELECT ctid, left(coded_element_key::text, 20) FROM coded_element WHERE ctid >= '(507577,1)';
    ctid    |   left   
------------+----------
 (507577,1) | 30010491
 (507577,2) | 30010507
 (507577,3) | 30010552
 (507577,4) | 30010556
 (507577,5) | 30010559
 (507577,6) | 30010564
 (507577,7) | 30010565
 (507577,8) | 30010625
 ...
 ...
 ...
 (507578,26) | 0A1717281.0002L270&.
 (507578,27) | L270&.*)0000.0000000
 (507578,28) | 30011452
 (507578,29) | -L0092917\x10)*(0117001
 (507578,30) | 0.00003840\x10)*)300114
ERROR:  invalid memory alloc request size 1908473862

问题是,当我进入/ data / base目录并找到表的相应文件时,该文件仅为1073741824字节。在块大小为8192字节的情况下,这仅使我获得了131072的块计数,位于507578值之下(假定的损坏所在)。这是确定块偏移量的正确方法还是其他方法?

postgresql block offset
1个回答
0
投票

PostgreSQL将表数据存储在大小为1GB的文件中。

假定结果

SELECT relfilenode
FROM pg_class
WHERE relname = 'coded_element';

是12345,这些文件将被称为1234512345.112345.2等。

由于这些1GB分段中的每个分段都包含131072块,所以块507578实际上是12345.4中的块114362。

数据损坏在该块中或在随后的块中。

此时,请确保您已经备份了完整的数据目录。

要将框507578归零,可以使用

dd if=/dev/zero of=12345.4 bs=8192 seek=114362 count=1 conv=notrunc,nocreat,fsync

如果不能解决问题,请尝试下一个步骤。

要在清零之前从块中挽救数据,可以使用pageinspect扩展名。

© www.soinside.com 2019 - 2024. All rights reserved.