PostgreSQL物理坏块和文件损坏案例分享
作者简介
王睿操,平安好医数据库架构岗,多年postgresql数据库运维开发工作。曾就职于中国民航信息,迪卡侬。对其他数据库产品也有一定的涉猎。
背景
笔者最近发现很多朋友经常遇到PostgreSQL坏块或者数据混乱的情况,网上中文资料比较少,于是整理了一下笔者遇到各种各样的报错以及解决方案
案例一:物理坏块
逻辑备份时报错
pg_dump: Dumping the contents of table "xxxx" failed: PQgetResult() failed.
pg_dump: Error message from server: ERROR: invalid memory alloc request size 18446744073709551613
pg_dump: The command was: COPY xxxxxx (id, active_flag, bkd, blk, go_show, grs, lss, lsv, lt, no_show, value, wl, inv_seg_cabin_id, ind) TO stdout;
pg_dump: [parallel archiver] a worker process died unexpectedly
原因:数据库产生坏行(可能是硬件损坏,可能是一个bug(piece of memory gets overwritten by random data pg9.2之前版本),也有可能是不正确的硬件配置)
首先笔者考虑了pg自带参数zero_damaged_pages,将这个参数修改为true,但发现仍然是报错,看了下官方文档,这种方法不会对物理文件作修改,只是把内存上,损坏页面的缓存变为0。如果这个方法解决了报错,请将这表备份出来重新恢复,或者select到另一张表。
解决方式:删除损坏行
create extension hstore;(过程省略)
1、定义函数:
CREATE OR REPLACE FUNCTION
find_bad_row(tableName TEXT)
RETURNS tid
as $find_bad_row$
DECLARE
result tid;
curs REFCURSOR;
row1 RECORD;
row2 RECORD;
tabName TEXT;
count BIGINT := 0;
BEGIN
SELECT reverse(split_part(reverse($1), '.', 1)) INTO tabName;
OPEN curs FOR EXECUTE 'SELECT ctid FROM ' || tableName;
count := 1;
FETCH curs INTO row1;
WHILE row1.ctid IS NOT NULL LOOP
result = row1.ctid;
count := count + 1;
FETCH curs INTO row1;
EXECUTE 'SELECT (each(hstore(' || tabName || '))).* FROM '
|| tableName || ' WHERE ctid = $1' INTO row2
USING row1.ctid;
IF count % 100000 = 0 THEN
RAISE NOTICE 'rows processed: %', count;
END IF;
END LOOP;
CLOSE curs;
RETURN row1.ctid;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'LAST CTID: %', result;
RAISE NOTICE '%: %', SQLSTATE, SQLERRM;
RETURN result;
END
$find_bad_row$
LANGUAGE plpgsql;
2、通过函数查找问题行:
js1=# select find_bad_row('public.description');
NOTICE: LAST CTID: (78497,6)
NOTICE: XX000: invalid memory alloc request size 18446744073709551613
find_bad_row
--------------
(78497,6)
(1 row)
js1=# select * from xxxxxxx where ctid = '(78498,1)';
ERROR: invalid memory alloc request size 18446744073709551613
js1=# delete from xxxxxx where ctid = '(78498,1)';
在我们这里需要对xxxx表格进行处理
3、然后再执行pg_dump命令
详细分析可见:https://www.postgresql.org/message-id/54889986.3000308%40gmail.com
案例二:pgclog因断电文件损坏
pg_clog损坏
报错信息:Could not read from file ""pg_clog/0646"" at offset 243287
服务器异常断电,这台因为是测试库,所以没备份以及备库(所以对于dba来说备份就是生命啊,不管是测试库还是生产库一定要做好备份)
- 对数据库进行全库物理备份(为之后操作做保险)
- 用dd进行伪造这个数据块(数据块伪造全部提交),并且更改权限
for i in {1..262144}; do printf '\125'; done > committed
ls -l committed
od -xv committed | head
od -xv committed | tail
$ ls -l committed
-rw-r--r-- 1 root root 262144 2009-06-25 11:01 committed
$ od -xv committed | head
0000000 5555 5555 5555 5555 5555 5555 5555 5555
0000020 5555 5555 5555 5555 5555 5555 5555 5555
0000040 5555 5555 5555 5555 5555 5555 5555 5555
0000060 5555 5555 5555 5555 5555 5555 5555 5555
0000100 5555 5555 5555 5555 5555 5555 5555 5555
0000120 5555 5555 5555 5555 5555 5555 5555 5555
0000140 5555 5555 5555 5555 5555 5555 5555 5555
0000160 5555 5555 5555 5555 5555 5555 5555 5555
0000200 5555 5555 5555 5555 5555 5555 5555 5555
0000220 5555 5555 5555 5555 5555 5555 5555 5555
$ od -xv committed | tail
0777560 5555 5555 5555 5555 5555 5555 5555 5555
0777600 5555 5555 5555 5555 5555 5555 5555 5555
0777620 5555 5555 5555 5555 5555 5555 5555 5555
0777640 5555 5555 5555 5555 5555 5555 5555 5555
0777660 5555 5555 5555 5555 5555 5555 5555 5555
0777700 5555 5555 5555 5555 5555 5555 5555 5555
0777720 5555 5555 5555 5555 5555 5555 5555 5555
0777740 5555 5555 5555 5555 5555 5555 5555 5555
0777760 5555 5555 5555 5555 5555 5555 5555 5555
1000000
chown postgres.postgres committed
chmod 600 committed
mv -i committed $PGDATA/pg_clog/0646
注意这个只能解决这个问题,不可以修复底层文件的损坏,所以如果有备份还是备份还原比较好。
案例三:toast表损坏
missing chunk number x for toast value x in pg_toast_x
某张表关联的toast表发现数据损坏
解决方案引自:http://m.2cto.com/database/201802/720718.html
1、定位是哪张表的toast有问题:
select 2619::regclass;
regclass
--------------
pg_statistic
2、找到哪个表有问题后,先对该表做一下简单的修复:
REINDEX table pg_toast.pg_toast_2619;
REINDEX table pg_statistic;
VACUUM ANALYZE pg_statistic;
3、定位该表中损坏的数据行。执行
DO $$
declare
v_rec record;
BEGIN
for v_rec in SELECT * FROM pg_statistic loop
raise notice ‘Parameter is:‘, v_rec.ctid;
raise notice ‘Parameter is:’, v_rec;
end loop;
END;
$$
LANGUAGE plpgsql;
4、将第3步中定位的记录删除:
delete from pg_statistic where ctid ='(50,3)';
5、重复执行第3,4步,直到全部有问题的记录被清除。
6、至此,toast问题就解决完了,解决之后,对数据库进行一次完整的维护或者索引重建。
其实一般来说,数据库会根据归档或者wal去自行将postgres中未提交事务进行回滚操作,笔者这个环境当时是因为缺失了归档,所以只能手动将混乱数据进行删除。
最后,笔者想说,很多情况下都是因为没有一个靠谱的备份而导致很多问题,所以建议大家不管什么情况,备份为先,检查备份很重要!
转载自:
http://blog.sina.com.cn/s/blog_67d069a90102vibc.html
PostgreSQL物理坏块和文件损坏案例分享的更多相关文章
- 12 oracle 数据库坏块--物理坏块-ORA-01578/ORA-01110
oracle 数据库坏块--物理坏块 数据坏块的类型物理坏块:通常是由于硬件损坏如磁盘异常导致.内存有问题.存储链有问题. IO有问题.文件系统有问题. Oracle本身的问题等逻辑坏块:可能都是软件 ...
- PostgreSQL 索引坏块处理
今天应用反应有张表查询报错,报错信息如下 back=# select max(create_time) from public.tbl_index_table where create_time> ...
- 对Oracle数据库坏块的理解
1.物理坏块和逻辑坏块 在数据库中有一个概念叫做数据块的一致性,Oracle的数据块的一致性包括了两个层次:物理一致性和逻辑一致性,如果一个数据块在这两个层次上存在不一致性,那就对应到了我们今天要要说 ...
- Oracle corrupt block(坏块) 详解
转自:http://blog.csdn.net/tianlesoftware/article/details/5024966 一. 坏块说明 1.1 相关链接 在看坏块之前,先看几个相关的链接,在后面 ...
- Oracle 处理坏块
本文主要介绍如何去处理在Oracle数据库中出现坏块的问题,对于坏块产生在不同的对象上,处理的方法会有所不同,本文将大致对这些方法做一些介绍.因为数据库运行时间长了,由于硬件设备的老化,出现坏块的几率 ...
- 【转载】 使用rman进行坏块修复(ORA-01578、ORA-01110)
[转自]http://blog.itpub.net/21256317/viewspace-1062055/ 使用rman进行坏块修复(ORA-01578.ORA-01110) 2012年的一天,处理的 ...
- HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()
无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...
- 13 oracle数据库坏块-逻辑坏块(模拟/修复)
13 oracle数据库坏块-逻辑坏块 逻辑数据坏块的场景1)oracle bug也可能导致逻辑坏块的产生. 特别是parallel dml. 例如:Bug 5621677 Logical corru ...
- Oracle current redo.log出现坏块后的不完全恢复案例一则
1异常出现 8月30日下午2时左右,接同事电话,说数据库异常宕机了,现在启动不了. 2初步分析 我让现场把alert.log发过来,先看看是什么问题. 关于ORA-00353和ORA-0 ...
随机推荐
- 利用Matlab实现PID控制仿真
该文转自博客园: https://www.cnblogs.com/kui-sdu/p/9048534.html %PID Controller clear, clc, close all; ts=0. ...
- Eclipse Block Selection(块选择)快捷键 Alt + Shift + A
说实话,我暂时还没用过这个快捷键.但是不代表以后我也不会用它. Eclipse 有个地方可以专门查看这些小技巧. Help → Tip of the Day 进入下面这个窗口: 将 Unread on ...
- 【scratch3.0教程】1.2 下载安装scratch
第2课 下载安装Scratch 1 . 什么是Scratch? Scratch将程序语言设计成一块块积木,你只要用拖拉的方式,将程序积木 ...
- mysql sql 分析
一.SQL 执行时间分析通过找到执行时间长的 SQL 语句,可以直观的发现数据层的效率问题. 1.通过 show processlist 来查看系统的执行情况mysql> show proces ...
- Node模块化
Node.js是一个能够在服务器端运行JavaScript的开放源代码.跨平台JavaScript运行环境.Node是对ES标准一个实现,也是一个JS引擎.与传统服务器不同是Node的服务器是单线程的 ...
- UOJ343 清华集训2017 避难所 构造、打表
传送门 玄学题 考虑构造三个数\(p_1p_2,p_1p_2,p_1p_2\)满足贪心分解会分解为\(p_1^3,p_2,p_2,p_2\),那么需要满足条件 1.\(p_1 , p_2 \in Pr ...
- Redis之RDB和AOF持久化介绍
什么是数据库状态 redis是一个键值对的数据库服务器,服务器中通常包含中任意个非空的数据库,而每个数据库又可以包含任意个键值对,为了方便起见,我们将服务器中的非空数据库以及他们的键值对统称为数据库状 ...
- 记redis一次Could not get a resource from the pool 异常的解决过程
最近有个项目中的redis每天都会报 "Could not get a resource from the pool"的错误,而这套代码在另一地方部署又没有问题.一直找不到错误原因 ...
- js json数据保存到本地
转自:https://www.cnblogs.com/gamedaybyday/p/9906542.html 使用HTML5来实现本地文件读取和写入 (FileReader读取json文件,File ...
- 忽略警告@SuppressWarnings的用法
@SuppressWarnings注解用法 @SuppressWarnings注解主要用在取消一些编译器产生的警告对代码左侧行列的遮挡,有时候这会挡住我们断点调试时打的断点. 我们可以在方法上加上@S ...