PostgreSQL could not read block 0 in file “base/16384/17330“: read only 0 of 8192 bytes错误

如果日志中出现类似下面的信息:

could not read block 0 in file "base/16384/17330": read only 0 of 8192 bytes

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

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

当发生损坏的表以及损坏的页面数量较少时,解决方法如下:

1.确定发生问题的数据库。连接任意数据库,执行下面的sql语句:
select datname from pg_database where oid = 16384;

查询结果:testdb

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

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

select relname,relkind from pg_class where relfilenode = 17330

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

例如:tb_door, r

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

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

例如:tb_door_index, i

或者:tb_door_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_door为例,则依次执行下列命令即可完成修复:

set zero_damaged_pages = on;

vacuum tb_door;

reindex table tb_door;

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

set zero_damaged_pages = on;

reindex index tb_door_index;

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

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

查询结果:tb_door, tb_door_pkey

然后获取索引的定义:

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

查询结果:PRIMARY KEY (id)

然后重新创建这个约束:

alter table tb_door drop constraint tb_door_pkey;

alter table tb_door add constraint tb_door_pkey PRIMARY KEY (id);

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值