1.使用oracle用户登录linux服务器,并进入sql模式
# sqlplus /nolog
2.超级管理员的权限操作数据库
# conn /as sysdba;
select name, status from v$datafile order by file#;
# recover datafile
# select status from v$datafile where file# = 6;
# alter database datafile 13 online;
# select name, status from v$datafile order by file#;
参考了很多优秀博主的文章 可是有些不适用,便自己整理了一下
操作需要用超级管理员登录,下面用的是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能执行查询语句,否则看不到错误点在哪里
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