oracle用户下执行dbv file='/var/oradata/test/system01.dbf' 检查这个文件是否有坏块
示例如下:
1.获取所有数据文件的检查脚本
select 'dbv file='||''''||name||'''' from v$datafile; --得出所有数据文件的检查脚本
dbv file='/var/oradata/test/system01.dbf'
dbv file='/var/oradata/test/TEST_D_TEST86_TEMP2.dbf'
dbv file='/var/oradata/test/sysaux01.dbf'
dbv file='/var/oradata/test/undotbs01.dbf'
2.将以上都放到1.sh文件中
vi 1.sh
dbv file='/var/oradata/test/system01.dbf'
dbv file='/var/oradata/test/TEST_D_TEST86_TEMP2.dbf'
dbv file='/var/oradata/test/sysaux01.dbf'
dbv file='/var/oradata/test/undotbs01.dbf'
3.执行脚本sh 1.sh > 1.log >2&1
4.最后查看结果
cat 1.log | egrep "FILE|Total Pages Marked Corrupt"
如果每个文件的Total Pages Marked Corrupt这一列都是0的话证明没有坏块。
补充说明:sql语句的拼接。
select 'dbv file='||''''||name||'''' from v$datafile;
用||进行拼接,其他字符串需要使用两个单引号括起来,特殊字符也需要用单引号进行转义。
select tablespace_name,segment_type,owner,segment_name from dba_extents where file_id=28 and 3085095 between block_id AND block_id + blocks - 1;
如果以上查出来的是lob字段的话,则需要通过如下语句查出是哪个表上的lob字段
select table_name from dba_lobs where segment_name=''
案例分享:
用dbv扫的时候发现某个文件坏了4个块:
dbv扫描之后,视图V$DATABASE_BLOCK_CORRUPTION为空,不确定是哪个块号有问题。
于是用如下的语句找出具体哪个文件的块坏了
发现是69号文件的1772816,1772885,1773338,1773402这4个块坏了。
具体语句如下:(因为是from dual,所以随便查那个库都可以)
select dbms_utility.data_block_address_file(291179792),dbms_utility.data_block_address_block(291179792),
dbms_utility.data_block_address_file(291179861),dbms_utility.data_block_address_block(291179861), dbms_utility.data_block_address_file(291180314),dbms_utility.data_block_address_block(291180314), dbms_utility.data_block_address_file(291180378),dbms_utility.data_block_address_block(291180378)
from dual;
再根据如下语句查这些块对应的对象是哪个
SELECT segment_type, owner, segment_name
FROM dba_extents
WHERE (file_id = 69 and 1772816 between block_id AND block_id + blocks - 1)
or
(file_id = 69 and 1772885 between block_id AND block_id + blocks - 1)
or
(file_id = 69 and 1773338 between block_id AND block_id + blocks - 1)
or
(file_id = 69 and 1773402 between block_id AND block_id + blocks - 1)
如果对应的对象是lob对象的话,再查这个lob是属于哪个表
select e.owner, l.table_name, l.segment_name
from dba_extents e, dba_lobs l
where e.owner = l.owner
and e.segment_name = l.segment_name
and e.segment_type = 'LOBSEGMENT'
and l.segment_name='SYS_LOB0001459936C00001$$';
停业务,重建表
如果是表的lob字段损坏的话,可以考虑重建这个表,如果表的数据量不大的话,可以先执行
alter system set events='10231 trace name context forever,level 10';
然后在create table as select * from 表这种方式重建表,重建索引,然后alter system set events '10231 trace name errorstack off'; 关闭跟踪。
如果表很大的话,可以先执行alter system set events='10231 trace name context forever,level 10';然后用数据泵导出导入表。然后alter system set events '10231 trace name errorstack off'; 关闭跟踪。(检查索引有效性)
如果业务不能停的话可以先将表重命名再重建或在导。
当时重建表的时候有这个报错
(create table T_CSL_CLSREPORT_bak0731 as select * from T_CSL_CLSREPORT不会报错,但是create table T_CSL_CLSREPORT as select * from T_CSL_CLSREPORT_bak0731 再建回去的时候会报下面的错)
解决方法可以参考链接:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/126119132
最后记得索引要重新建上,关闭跟踪
如果数据库中多个数据文件都存在坏块的情况(包括system系统文件) 建议找时间停应用服务之后 再在数据库服务器上执行 sqlplus / as sysdba
alter system set events='10231 trace name context forever,level 10';
然后expdp导出数据,dbca新建一个数据库(不能在用原来的数据库实例了),
再impdp导入到新的数据库中。 最后再在应用服务器连接新的这个数据数据库给用户使用。