PostgreSQL 文件块损坏

原文链接: https://blog.csdn.net/qq_25938327/article/details/125111477

异常信息

could not read block 1971 in file \"base/16413/35496215\": read only 4992 of 8192 bytes

分析

以上日志表示数据表文件损坏。这通常是由于异常断电或误操作导致的。这里“16413”是发生问题的数据库的对象id(oid), “35496215”表示发生问题的表的文件结点(filenode)

如果发生损坏的表以及损坏的页面数量较少,我们可以以牺牲部分数据的代价恢复整体;如果损坏的表数量过多,或者损失的数据非常重要,就需要从备份中恢复数据了。

当发生损坏的表以及损坏的页面数量较少时,解决方法如下:
1.确定发生问题的数据库。连接任意数据库,执行下面的sql语句:

select datname from pg_database where oid = 16413;

查询结果:testdb

这表示发生问题的数据库名是testdb

2.查找损坏的数据库对象。连接发生问题的数据库,执行下面的sql语句:

select relname,relkind from pg_class where relfilenode = 35496215

如果查询结果中 relkind = r,表示损坏的是表。

例如:tb_test, r

relname = tb_test这表示损坏的表是tb_test。

如果查询结果中relkind = i,表示损坏的是一个索引。

例如:tb_test_index, i

或者:tb_test_pkey, i

需要注意,损坏的可能是普通索引,也可能是主键或唯一键。如果索引的名称中有"_pkey"等很可能属于主键,而名称中含有 "_key"则很可能属于唯一键。

还需要格外注意一点,表/索引可修复的前提条件是损坏的表是应用程序创建的表/索引,而不是PostgreSQL的系统表和建立在其上的索引。如果系统表/建立在其上的索引发生损坏,则需要从备份中恢复数据库。判断一个表是否是系统表,最简单的方法是:如果表名是“pg_”开头的,则说明它是系统表。

pgclass.relkind 的值有下面几种:

r表示ordinary table(普通表)

i表示index(索引)

s表示sequence(序列)

v表示view(视图)

m表示materialized view(物化视图)

c表示composite type(复合类型)

t表示TOAST table(TOAST 表)

f表示foreign table(外部表)

3. 修复损坏的数据库对象。连接发生损坏的数据库,执行修复命令。

如果损坏的是表,以tb_test为例,则依次执行下列命令即可完成修复:

set zero_damaged_pages = on;

vacuum tb_door;

reindex table tb_test;

如果损坏的是普通索引,以tb_test_index为例, 则依次执行:

set zero_damaged_pages = on;

reindex index tb_test_index;

如果损坏的是主键或唯一键,则首先需要找到它所在的表,以tb_test_pkey为例:

select tablename,indexname from pg_indexes where indexname = "tb_test_pkey";

查询结果:tb_test, tb_test_pkey

然后获取索引的定义:

select pg_get_constraintdef((select oid from pg_constraint where conname = "tb_test_pkey"));

查询结果:PRIMARY KEY (id)

然后重新创建这个约束:

alter table tb_test drop constraint tb_test_pkey;

alter table tb_test add constraint tb_test_pkey PRIMARY KEY (id);

你可能感兴趣的:(SQL,postgresql,block,error)