28-ORA-01110数据文件读取错误

文章目录

  • [ORA-01110: error in data file n](#ORA-01110: error in data file n)
    • 一、报错现象(原文)
    • 二、原因分析
    • [三、场景一:文件找不到(ORA-01157 + ORA-01110)](#三、场景一:文件找不到(ORA-01157 + ORA-01110))
      • [3.1 判断文件是真丢还是假丢](#3.1 判断文件是真丢还是假丢)
      • [3.2 有备份:标准恢复](#3.2 有备份:标准恢复)
      • [3.3 无备份且数据可弃:offline drop 保全库](#3.3 无备份且数据可弃:offline drop 保全库)
      • [3.4 路径变了:rename datafile](#3.4 路径变了:rename datafile)
    • [四、场景二:块损坏(ORA-01578 + ORA-01110)](#四、场景二:块损坏(ORA-01578 + ORA-01110))
      • [4.1 定位坏块归属](#4.1 定位坏块归属)
      • [4.2 DBV 全文件校验,确认损坏范围](#4.2 DBV 全文件校验,确认损坏范围)
      • [4.3 修复](#4.3 修复)
    • [五、vdatafile 状态速查表](#五、vdatafile 状态速查表)
    • 六、验证
    • 七、预防

ORA-01110: error in data file n

一、报错现象(原文)

ORA-01110 自己的内容很简单:

复制代码
ORA-01110: data file 5: '/u01/app/oracle/oradata/orcl/users01.dbf'

只有文件号和路径,没有别的信息。这是因为它几乎从不单独出现------ORA-01110 的作用是给前面的主错误补充"哪个文件出的事"这行线索。常见三种组合:

复制代码
-- 组合一:文件找不到(启动时)
ORA-01157: cannot identify/lock data file 5 - see DBWR trace file
ORA-01110: data file 5: '/u01/app/oracle/oradata/orcl/users01.dbf'

-- 组合二:文件校验失败(启动时)
ORA-01122: database file 5 failed verification check
ORA-01110: data file 5: '/u01/app/oracle/oradata/orcl/users01.dbf'

-- 组合三:块损坏(运行期,查某张表时)
ORA-01578: ORACLE data block corrupted (file # 5, block # 128)
ORA-01110: data file 5: '/u01/app/oracle/oradata/orcl/users01.dbf'

处理思路也由此而来:ORA-01110 负责指路,真正的原因和修法看伴随错误,分三条线走。

二、原因分析

复制代码
ORA-01110(哪个文件)
   │
   ├──► 伴随 ORA-01157:文件不在/读不了 ──► 被删、路径变、权限
   │
   ├──► 伴随 ORA-01122:文件头对不上 ──► 旧备份文件、SCN 不一致(见 26/27 篇)
   │
   └──► 伴随 ORA-01578:块级损坏 ──► 存储坏块、异常断电

三、场景一:文件找不到(ORA-01157 + ORA-01110)

3.1 判断文件是真丢还是假丢

复制代码
$ ls -l /u01/app/oracle/oradata/orcl/users01.dbf
ls: cannot access ...: No such file or directory   -- 真没了

$ ls -l ...
-rw-r--r-- 1 root root ... users01.dbf             -- 在,但属主是 root:权限问题

Windows 环境先看回收站,误删的文件经常还能直接还原。同时查库内登记:

sql 复制代码
SQL> startup mount
SQL> select file#, name, status from v$datafile where file# = 5;

3.2 有备份:标准恢复

复制代码
RMAN> startup mount
RMAN> restore datafile 5;
RMAN> recover datafile 5;
RMAN> alter database open;

3.3 无备份且数据可弃:offline drop 保全库

先把库开起来,不让一个文件拖死整库:

sql 复制代码
SQL> startup mount
SQL> alter database datafile 5 offline drop;

Database altered.

SQL> alter database open;

offline drop 不是删文件,是把该文件标记为脱离,让 open 跳过它------文件上的数据等于放弃了。之后清掉旧登记、重建表空间:

sql 复制代码
-- 能导的数据先导(exp/expdp 该表空间下还能读的对象)
SQL> drop tablespace users including contents and datafiles;
SQL> create tablespace users
  2  datafile '/u01/app/oracle/oradata/orcl/users01.dbf' size 500m;

限制:system / sysaux 表空间的文件不能走这条路,只能 restore 恢复。

3.4 路径变了:rename datafile

文件还在,只是挪了位置(换盘、迁移存储),两种改法:

方法一,库能到 mount(适用于 system 表空间等任何文件):

sql 复制代码
SQL> startup mount
-- 操作系统层先移动文件:
-- mv /u01/old/users01.dbf /u02/new/users01.dbf
SQL> alter database rename file '/u01/old/users01.dbf'
  2  to '/u02/new/users01.dbf';
SQL> alter database open;

方法二,非 system 表空间且库是开的:

sql 复制代码
SQL> alter tablespace users offline;
-- 操作系统层移动文件
SQL> alter tablespace users rename datafile '/u01/old/users01.dbf'
  2  to '/u02/new/users01.dbf';
SQL> alter tablespace users online;

两步都别忘了"先在操作系统层把文件放到新路径",rename 只改控制文件里的登记,不搬文件。

四、场景二:块损坏(ORA-01578 + ORA-01110)

4.1 定位坏块归属

alert log 里的报错直接给了坐标:

复制代码
ORA-01578: ORACLE data block corrupted (file # 5, block # 128)
ORA-01110: data file 5: '...'

查这个块属于哪个对象:

sql 复制代码
select owner, segment_name, segment_type
from dba_extents
where file_id = 5
  and 128 between block_id and block_id + blocks - 1;

OWNER  SEGMENT_NAME     SEGMENT_TYPE
------ ---------------- -------------
SCOTT  BIG_ORDER        TABLE

4.2 DBV 全文件校验,确认损坏范围

复制代码
$ dbv file=/u01/app/oracle/oradata/orcl/users01.dbf blocksize=8192

DBVERIFY: Release 11.2.0.4.0 - Production on Mon Sep 28 10:00:00 2026

Total Pages Examined         : 64000
Total Pages Processed (Data) : 51234
Total Pages Marked Corrupt   : 2

重点看 Total Pages Marked Corrupt,它可能比 alert 里报的多------把范围一次摸清,别修一个又冒一个。Windows 下路径换写法即可:

复制代码
C:\> dbv file=D:\app\oracle\oradata\orcl\users01.dbf blocksize=8192

RMAN 也可以做校验,结果落在视图里:

复制代码
RMAN> backup validate check logical datafile 5;
sql 复制代码
SQL> select * from v$database_block_corruption;

4.3 修复

有备份,块级恢复,不用整文件 restore:

复制代码
-- 11g 及以前
RMAN> blockrecover datafile 5 block 128;

-- 12c 及以后写法
RMAN> recover corruption list;

无备份,以抢救数据为主。按 rowid 范围分批导出好块,绕开坏块,然后重建表:

sql 复制代码
select dbms_rowid.rowid_create(1, data_object_id, 5, 128, 0) min_rid,
       dbms_rowid.rowid_create(1, data_object_id, 5, 129, 0) max_rid
from dba_objects
where owner = 'SCOTT' and object_name = 'BIG_ORDER';
-- 用得到的 rowid 范围做 create table t as select ... where rowid between ...
-- 多段范围拼接,跳过损坏块

应急跳过坏块(全表扫描不再报错,但坏块数据不完整):

sql 复制代码
SQL> alter session set events '10231 trace name context forever, level 10';

这是应急手段,导完数据就关,不是让库带病长期运行的姿势。

五、v$datafile 状态速查表

排查时随手一条:

sql 复制代码
select file#, name, status from v$datafile;
status 含义 处理方向
SYSTEM system 表空间文件,在线 正常
ONLINE 在线,正常 正常
OFFLINE 被手工脱机 确认后 online,或继续恢复
RECOVER 需要介质恢复 recover datafile(见 27 篇)
SYSOFF 系统表空间文件处于脱机(异常状态) 恢复流程

配合 v$datafile_header 交叉验证(文件头层面的视角):

sql 复制代码
select file#, status, fuzzy, checkpoint_change# from v$datafile_header;

六、验证

sql 复制代码
-- 文件层面:状态全部正常
SQL> select file#, status from v$datafile;

-- 恢复层面:没有待恢复文件
SQL> select * from v$recover_file;
no rows selected

-- 块层面:DBV 复跑一遍,Marked Corrupt 为 0
-- $ dbv file=... blocksize=8192

最后业务侧抽查:坏块所属表 count 一下、关键行读一遍,能读就是修干净了。

七、预防

  • 数据文件的唯一保险是备份:RMAN 定期全备 + 归档,并确保 restore/recover/blockrecover 都演练过
  • 块损坏多源于存储层坏块和异常断电,RAID 健康巡检、UPS 比事后修复便宜得多
  • 迁移文件走 rename 流程(操作系统移动 + rename 登记),不要手工 mv 完就不管
  • 定期 backup validate 扫描数据文件,坏块在备份阶段发现,永远比在业务查询时报 ORA-01578 要体面
相关推荐
凯凯姜1 小时前
MySQL 联合索引设计与索引失效
数据库·mysql
猫咪很可爱2 小时前
Oracle TEMP 表空间不足(ORA-01652)问题分析与优化实践
数据库·oracle
九零HTTP3 小时前
10月21号-CSDN配菜-IP池的5个坑
服务器·数据库·tcp/ip
Data-Miner3 小时前
需要做财务数据分析,有什么好用的工具?从准备到出报告的实操指南
大数据·数据库·数据分析
袋鼠云数栈4 小时前
让 SQL 解析不再重复造轮子:SqlParserX 正式开源
数据库·人工智能·sql·开源·数据治理
这个DBA有点耶4 小时前
期货 CTP 系统 Oracle RAC 迁移国产库实战:读写分离架构设计与性能对标
数据库·架构·dba
数据库安全4 小时前
AI数据访问安全 |如何控制AI访问权限,防止越权
数据库·安全
这个DBA有点耶5 小时前
Redo Log循环写与checkpoint推进:长事务阻塞下的Checkpoint风暴完整链路
数据库·mysql·代码规范
jnrjian5 小时前
pg_waldump --key-file-name status 查看wal 产生的db
数据库