欢迎投稿

今日深度:

ORA-01578、ORA-01110:数据块被损坏,此时无法读取文件问题修复方案,

ORA-01578、ORA-01110:数据块被损坏,此时无法读取文件问题修复方案,


目录
  • 查看问题:
    • 1.使用oracle用户登录linux服务器,并进入sql模式
    • 2.超级管理员的权限操作数据库
    • 3.查询不在线的数据
    • 4.恢复数据
    • 5.再次查询文件数据 文件为脱机状态
    • 6.将文件挂上网
    • 7.确认文件状态
    • 8.文件已经上线,可能还会出现一些问题 BLOB字段损坏导致部分表无法使用
  • 原因分析:
    • 表修复方案:
      • 方案一 可视化处理坏块(亲测有效):
      • 方案二(查询坏块的rowid进行处理):
      • 方案三(建立中间表处理):
      • 方案四(重新导入可用数据):
      • 方案五(通过数据库直接建备份表转换):
    • 总结

      查看问题:

      1.使用oracle用户登录linux服务器,并进入sql模式

      # sqlplus /nolog

      2.超级管理员的权限操作数据库

      # conn /as sysdba;

      3.查询不在线的数据

      select name, status from v$datafile order by file#;

      4.恢复数据

      # recover datafile

      5.再次查询文件数据 文件为脱机状态

      # select status from v$datafile where file# = 6;

      6.将文件挂上网

      # alter database datafile 13 online;

      7.确认文件状态

      # select name, status from v$datafile order by file#;

      8.文件已经上线,可能还会出现一些问题 BLOB字段损坏导致部分表无法使用

      参考了很多优秀博主的文章 可是有些不适用,便自己整理了一下

      原因分析:

      1.重启数据库 导致oracle在操作blob字段有问题。

      2.应用操作数据库事,产生了锁等待。

      3.出现锁等待,可以通过后台日志查看,后台会有对应的抛出一个ORA-00600错误。

      4.根据 ORA-00600 错误跟踪,发现是一个INSERT 语句插入导致(可能是坏块造成),在数据库重启时插入数据有问题。  

      5.通过select count(*) from user.table;查询对应的表会抛出错误,说明此数据文件下的某个块存在问题;

      表修复方案:

      方案一 可视化处理坏块(亲测有效):

      操作需要用超级管理员登录,下面用的是plsql 也可以用控制台

      1.查询坏块对应的分段类型、所属、分段名称

      SELECT SEGMENT_TYPE, OWNER, SEGMENT_NAME
        FROM DBA_EXTENTS
       WHERE FILE_ID = 6
         AND 1962511 BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS - 1;
       
      -- FILE_ID 文件标识  1962511 坏块的标识 可通过报错获取

       2.查询坏块的对应表

      select table_name, column_name
        from dba_lobs
       where segment_name = 'SYS_LOB0000086896C00002$$'
         and owner = 'HLT20230606';
      -- segment_name 分段名称 上一条语句中获取  owner 所有者

      3.根据表及字段查看到数据缺失有损坏,删除损坏块即可,置空应该也可以

      select * from HLT20230606.S_BS_UIVIEWEXT;
      DELETE FROM HLT20230606.S_BS_UIVIEWEXT WHERE FID = 'AnwAAACllIjajtru'

       优势:可视化发现错误并可以直接通过语句清理

       劣势:需要sql能执行查询语句,否则看不到错误点在哪里

      方案二(查询坏块的rowid进行处理):

      1.通过表空间 object_id,file_ID,block#,row# 构造ROWID 1)通过FILE_ID,BLOCK 查询出

      segment_name:

      SELECT SEGMENT_TYPE, OWNER, SEGMENT_NAME FROM DBA_EXTENTS
       WHERE FILE_ID = 6 
       AND 1962511 BETWEEN BLOCK_ID AND BLOCK_ID+BLOCKS

       2.构造坏块的ROWID

      SELECT DATA_OBJECT_ID FROM USER_OBJECTS WHERE OBJECT_NAME = 'SYS_LOB0000086896C00002$$';

      不懂为啥查不出来

      SELECT DBMS_ROWID.ROWID_CREATE(1, 54649, 39, 24961, 0) FROM DUAL;
      -- 54649 上面查出来的

      3.通过ROWID 查询对应的列数据,并处理 

      SELECT ROWID,XXX FROM TABLE_NAME

      优势:直接定位到有问题的数据

      劣势:不懂为啥查不到数据

      方案三(建立中间表处理):

      1.建临时表

      create table corrupted_lob_data (corrupted_rowid rowid);

       2.设置凹入

      set concat off

      3.打开设置输出服务器

      set serveroutput on

       4.执行存过

      declare
        error_1555 exception;
        pragma exception_init(error_1555, -1555);
        num number;
      begin
        for cursor_lob in (select rowid r, &&lob_column
                             from &table_owner. &table_with_lob) loop
          begin
            num := dbms_lob.instr(cursor_lob.FSQL, hextoraw('889911'));
          exception
            when error_1555 then
              insert into corrupted_lob_data values (cursor_lob.r);
              commit;
          end;
        end loop;
      end;

       5.获取有问题数据

      select * from corrupted_lob_data;
      select * from table(坏块的表) where rowid='AAEtzZAAOAACBpiAAP' ;--(BLOB坏的字段会出现ERROR字样)

      通过上面的sql执行获取到具体哪些数据有问题,并对这些数据进行处理。

      优势:循坏遍历到各个问题数据并放入中间表,更快的定位问题数据

      劣势:执行存过报错的话,没办法解决

      方案四(重新导入可用数据):

       1.10231 内部事件,设置在全表扫描时跳过损坏的数据块.

      alter system set events='10231 trace name context forever,level 10'; 

      2.导出对应的表信息 

      exp HLT20230606/kshdksk file=t.dmp tables=S_BS_UIVIEWEXT
      -- exp 用户名/密码@数据库 file=t.dmp tables=有问题的表

      3.删除表

      drop table t;

      4.导入备份表

      imp HLT20230606/kshdksk@orcl file=t.dmp tables=S_BS_UIVIEWEXT
      -- imp 用户名/密码@数据库 file=t.dmp tables=有问题表

      优势:直接整个问题表进行导入导出,对于数据量大的表,这种方式比较快

      劣势:直接跳过问题数据,无法直观的看到有问题的数据

      方案五(通过数据库直接建备份表转换):

       1.查询坏块对应的分段类型、所属、分段名称

      SELECT SEGMENT_TYPE, OWNER, SEGMENT_NAME
        FROM DBA_EXTENTS
       WHERE FILE_ID = 6
         AND 1962511 BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS - 1;
       
      -- FILE_ID 文件标识  1962511 坏块的标识 可通过报错获取

       2.查询坏块的对应表

      select table_name, column_name
        from dba_lobs
       where segment_name = 'SYS_LOB0000086896C00002$$'
         and owner = 'HLT20230606';
      -- segment_name 分段名称 上一条语句中获取  owner 所有者

      3.使用10231事件忽略坏块

      alter session SET EVENTS '10231 trace name context forever,level 10';

      4.使用CTAS方式重建表

      create table S_BS_UIVIEWEXT_NEW as select * from S_BS_UIVIEWEXT;

       5.重命名表rename table

      rename S_BS_UIVIEWEXT to S_BS_UIVIEWEXT_BAK;
      rename  S_BS_UIVIEWEXT_NEW to  S_BS_UIVIEWEXT;

      6.重建索引rebuild index

      alter index PK_BS_UIVIEWEXT rebuild;

      7.关闭忽略坏块

      alter session SET EVENTS '10231 trace name context off';

      优势:直接整个问题表进行重建,对于数据量大的表,这种方式比较快

      劣势:直接跳过问题数据,无法直观的看到有问题的数据

      对象方案修复:

      对于对象 可以直接重建对象

      alter index indexname rebuild

      总结

      到此这篇关于ORA-01578、ORA-01110:数据块被损坏,此时无法读取文件问题修复方案的文章就介绍到这了,更多相关ORA-01578 ORA-01110数据块被损坏内容请搜索PHP之友以前的文章或继续浏览下面的相关文章希望大家以后多多支持PHP之友!

      您可能感兴趣的文章:
      • Oracle数据块损坏之10231内部事件不完全恢复

      www.htsjk.Com true http://www.htsjk.com/oracle/47717.html NewsArticle ORA-01578、ORA-01110:数据块被损坏,此时无法读取文件问题修复方案, 目录 查看问题: 1.使用oracle用户登录linux服务器,并进入sql模式 2.超级管理员的权限操作数据库 3.查询不在线的数据...
      评论暂时关闭