文章目录
- [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 要体面