篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录一次金仓V8R3数据库坏块处理过程PostgreSQL数据库适用相关的知识,希望对你有一定的参考价值。
因数广政务云华为业务存储固件升级,导致数据库产生坏块,业务SQL查询报错如下:
ERROR: missing chunk number 0 for toast value 38166585 in SYS_TOAST_30170
CONTEXT: PL/SQL function inline_code_block line 12 at FOR over EXECUTE statement
解决办法:
1、先查询出 SYS_TOAST_30170 属于哪张表的大字段。
select
n.nspname AS schema_name,
c.relname AS table_name,
a.attname AS column_name,
bb.relname as TOAST_name
from
sys_class c
inner join (select substring(sc.RELNAME from \'[0-9]+\') gg, sc.relname from sys_class sc) bb on c.relfilenode = bb.gg
inner join sys_attribute a on a.attrelid = c.oid
inner join sys_namespace n ON n.oid = c.relnamespace
WHERE
a.attnum > 0
AND NOT a.attisdropped
AND a.atttypid = (SELECT oid FROM sys_type WHERE typname = \'text\')
and bb.relname = \'SYS_TOAST_30170\';
PostgreSQL使用以下脚本:
select
n.nspname AS schema_name,
c.relname AS table_name,
a.attname AS column_name,
bb.relname as TOAST_name
from
pg_class c
inner join (select substring(sc.RELNAME from \'[0-9]+\') gg, sc.relname from pg_class sc) bb on c.relfilenode = bb.gg
inner join pg_attribute a on a.attrelid = c.oid
inner join pg_namespace n ON n.oid = c.relnamespace
WHERE
a.attnum > 0
AND NOT a.attisdropped
AND a.atttypid = (SELECT oid FROM pg_type WHERE typname = \'text\')
and bb.relname = \'SYS_TOAST_30170\';
2、创建一张记录含有坏块行的表、row_error_table
CREATE TABLE row_error_table (
err_ctid tid,
err_tablename varchar2(1000),
err_cloum varchar2(500),
err_CONTEXT text
);
3、使用下面脚本找到坏块在哪些行进行处理。
DO $$
DECLARE
rec RECORD;
v_tablename text := \'g_inbox\';
v_columnname text := \'PROCESS_CONTENT\';
BEGIN
FOR rec IN EXECUTE format(\'SELECT ctid, %I FROM %I ORDER BY ctid \', v_columnname, v_tablename) LOOP
BEGIN
RAISE NOTICE \'CTID Parameter is: %\', rec.ctid;
RAISE NOTICE \'ROW Parameter is: %\', rec.PROCESS_CONTENT;
EXCEPTION WHEN others THEN
INSERT INTO row_error_table (err_ctid, err_tablename,err_cloum,err_CONTEXT) VALUES (rec.ctid, v_tablename,v_columnname,SQLERRM);
END;
END LOOP;
END;
$$
LANGUAGE plsql;
这个脚本会对需要检测坏块的表进行全表扫描,逐行验证是否有坏块。
v_tablename text := \'g_inbox\'; /* 需要检测坏块的表、手动输入 */
v_columnname text := \'PROCESS_CONTENT\'; /* 需要检测坏块的列、手动输入 */
检测坏块的时间取决于表的数据量。
脚本跑完以后会显示DO。
4、上面脚本跑完以后检查哪些行是有坏块。
SELECT * FROM row_error_table;
保存坏块的表名和列名都有显示,保存着CTID。
5、校验行是否有坏块。
查询整行记录报错,确定是有坏块
6、找到坏块的主键id。
找到主键ID以后,可以通过备份集找到原来的备份在异机进行恢复,然后通过主键ID找到着5行数据导出,然后在生产库导入即可。
1. 执行sql:select count(distinct id) from bw_fpzxx ,报错如下:
ORA-01578: ORACLE 数据块损坏 (文件号 16, 块号 195428)
ORA-01110: 数据文件 16: ‘/disk01/hwxx09.dbf‘
01578. 00000 - "ORACLE data block corrupted (file # %s, block # %s)"
2.确认block_no 为195428的数据。
select id,rownum,rowid,dbms_rowid.rowid_relative_fno(rowid) rel_fno,dbms_rowid.rowid_block_number(rowid)
blockno from bw_fpzxx where dbms_rowid.rowid_relative_fno(rowid)=16 and
dbms_rowid.rowid_block_number(rowid)
=195428--rownum <8;
/*
1 1100623697598 1 AAASNhAAQAAAvtkAAL 16 195428
2 1100623690430 2 AAASNhAAQAAAvtkAAE 16 195428
3 1100623693502 3 AAASNhAAQAAAvtkAAH 16 195428
4 1100623687358 4 AAASNhAAQAAAvtkAAB 16 195428
5 1100623695550 5 AAASNhAAQAAAvtkAAJ 16 195428
6 1100623691454 6 AAASNhAAQAAAvtkAAF 16 195428
7 1100623698622 7 AAASNhAAQAAAvtkAAM 16 195428
8 1100623688382 8 AAASNhAAQAAAvtkAAC 16 195428
9 1100623694526 9 AAASNhAAQAAAvtkAAI 16 195428
10 1100623696574 10 AAASNhAAQAAAvtkAAK 16 195428
11 1100623692478 11 AAASNhAAQAAAvtkAAG 16 195428
12 1100623686334 12 AAASNhAAQAAAvtkAAA 16 195428
13 1100623689406 13 AAASNhAAQAAAvtkAAD 16 195428
*/
13条数据,把出错的数据块屏蔽了。
3.
alter system set event=‘10231 trace name context forever,level 10‘ scope=spfile;
4.再次执行sql
select count(distinct id) from bw_fpzxx;
147467803