Oracle 数据文件与表空间架构详解
Oracle 数据文件与表空间架构详解
适用版本:Oracle Database 19c / 23ai 阅读基础:了解 Oracle 物理结构和逻辑结构 文档版本:v1.0 / 2026-07
目录
- 1. 概述:Oracle 存储的分层架构
- 2. 物理结构:数据文件
- 3. 逻辑结构:表空间、段、区、块
- 4. 数据块内部结构
- 5. 表空间类型
- 6. 表空间管理方式
- 7. 标准表空间
- 8. 大文件表空间(Bigfile Tablespace)
- 9. 表空间相关视图
- 10. 表空间管理操作
- 11. 空间管理与碎片
- 12. 常见坑与排错
- 13. 最佳实践
- 14. 参考资料
1. 概述:Oracle 存储的分层架构
Oracle 数据库采用逻辑 + 物理分层存储架构[1][2]:
逻辑存储结构 物理存储结构
───────────── ─────────────
Database 数据库
↓ ↓
Tablespace(表空间) ←→ Datafile(数据文件)
↓ ↓
Segment(段) (在数据文件中)
↓
Extent(区)
↓
Data Block(数据块)
层级关系[1][2]:
- 一个数据库有多个表空间
- 一个表空间对应一个或多个数据文件
- 一个段跨多个区
- 一个区在单个数据文件内连续
- 一个数据块是最小 I/O 单位
类比:
| 层级 | 类比 |
|---|---|
| 表空间 | 书架 |
| 数据文件 | 书架的隔层 |
| 段 | 一本书 |
| 区 | 一章 |
| 数据块 | 一页纸 |
2. 物理结构:数据文件
数据文件(Datafile)是 Oracle 在操作系统层面的物理文件[1]。
核心特点:
- 只能属于一个表空间
- 一个表空间可包含多个数据文件
- 二进制文件,不能用文本编辑器查看
- 大小可固定或自动扩展
- 包含数据块和文件头
文件头内容:
- 数据文件号
- 所属表空间
- 检查点 SCN
- 重置日志 SCN
- 创建时间戳
查看数据文件:
SELECT file_name, file_id, tablespace_name,
bytes/1024/1024 AS size_mb,
status, autoextensible,
maxbytes/1024/1024 AS max_mb,
increment_by
FROM dba_data_files
ORDER BY tablespace_name, file_id;
3. 逻辑结构:表空间、段、区、块
3.1 表空间(Tablespace)
表空间是最大的逻辑存储单位[1][2]。
核心特点:
- 一个数据库至少有 SYSTEM、SYSAUX、TEMP、UNDOTBS 几个表空间
- 包含一个或多个数据文件
- 段不能跨表空间
- 区可以跨数据文件(同一表空间内)
表空间类型:
| 类型 | 说明 |
|---|---|
| Permanent | 永久表空间(SYSTEM, USERS 等) |
| Undo | Undo 表空间 |
| Temporary | 临时表空间(TEMP) |
3.2 段(Segment)
段是数据库对象占用的存储空间[1][2]。
段类型:
| 段类型 | 说明 |
|---|---|
| TABLE | 表段 |
| INDEX | 索引段 |
| CLUSTER | 簇段 |
| TABLE PARTITION | 表分区段 |
| INDEX PARTITION | 索引分区段 |
| LOBSEGMENT | LOB 数据段 |
| LOBINDEX | LOB 索引段 |
| ROLLBACK | 回滚段 |
| TEMPORARY | 临时段 |
| NESTED TABLE | 嵌套表段 |
查看段:
SELECT segment_name, segment_type, tablespace_name,
bytes/1024/1024 AS size_mb, extents, blocks
FROM dba_segments
WHERE owner = 'SCOTT'
ORDER BY bytes DESC;
3.3 区(Extent)
区是 Oracle 为段分配空间的最小单位[1][2],由连续的数据块组成。
核心特点:
- 连续性:区内的块在数据文件中物理连续
- 按需分配:段空间用完时自动分配新区
- 大小可变:初始区、后续区可不同大小
查看区分配:
SELECT segment_name, segment_type,
extent_id, file_id, block_id,
blocks, bytes/1024 AS size_kb
FROM dba_extents
WHERE owner = 'SCOTT' AND segment_name = 'EMP'
ORDER BY extent_id;
区分配策略(LMT UNIFORM):
CREATE TABLESPACE users
DATAFILE '/u01/oradata/orcl/users01.dbf' SIZE 100M
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
-- 每个区固定 1MB
区分配策略(LMT AUTOALLOCATE,默认):
CREATE TABLESPACE users
DATAFILE '/u01/oradata/orcl/users01.dbf' SIZE 100M
EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
-- Oracle 自动决定区大小(64K、1M、8M、64M)
3.4 数据块(Data Block)
数据块是 Oracle 最小的存储和 I/O 单位[1][2]。
核心参数:
| 参数 | 说明 | 典型值 |
|---|---|---|
DB_BLOCK_SIZE | 标准块大小 | 8KB(OLTP)/ 32KB(OLAP) |
| 块头 | 块地址、类型、事务信息 | 约 100 字节 |
| 表目录 | 块中数据的表信息 | 动态 |
| 行目录 | 行的偏移地址 | 动态 |
| 空闲空间 | 可用于插入或更新 | 动态 |
| 行数据 | 实际数据 | 主体 |
查看块大小:
SHOW PARAMETER db_block_size
-- 查看非标准块大小
SELECT tablespace_name, block_size
FROM dba_tablespaces;
坑 1:块大小在数据库创建后不能修改,需要重建数据库。
4. 数据块内部结构
数据块的物理结构[1]:
┌──────────────────────────────────┐
│ Block Header(块头) │
│ - 块地址 │
│ - 段类型 │
│ - 事务表(ITL,Interested Transaction List)│
│ - SCN │
├──────────────────────────────────┤
│ Table Directory(表目录) │
│ - 该块包含的表信息 │
├──────────────────────────────────┤
│ Row Directory(行目录) │
│ - 每行的偏移地址 │
├──────────────────────────────────┤
│ Free Space(空闲空间) │
│ - 用于插入和更新 │
├──────────────────────────────────┤
│ Row Data(行数据) │
│ - 实际表数据 │
└──────────────────────────────────┘
ITL(事务槽):
- 每个块头部有事务表
- 记录当前修改该块的事务
- 默认 2 个槽,可通过
INITRANS调整 - 满时会扩展到
MAXTRANS
PCTFREE 和 PCTUSED[1]:
| 参数 | 说明 | 默认 |
|---|---|---|
PCTFREE | 预留空间百分比,用于更新 | 10 |
PCTUSED | 块使用率低于此值时允许插入 | 40 |
块空间使用:
┌── 0% ──── PCTUSED ──── (100-PCTFREE)% ──── 100% ──┐
│ 空闲 可插入区 仅更新区 │
│ (不可插入) (已满不可插入) │
└─────────────────────────────────────┘
插入过程:空闲 → (100-PCTFREE)% → 停止插入
删除过程:(100-PCTFREE)% → PCTUSED → 允许再次插入
5. 表空间类型
| 类型 | 用途 | 示例 |
|---|---|---|
| Permanent | 永久存储业务数据 | SYSTEM, SYSAUX, USERS |
| Undo | 存储 Undo 数据 | UNDOTBS1 |
| Temporary | 临时数据(排序、哈希) | TEMP |
| Bigfile | 单文件大表空间 | 用户创建 |
| Encrypted | 加密表空间 | 安全场景 |
6. 表空间管理方式
6.1 区管理:DMT vs LMT
字典管理表空间(DMT,Dictionary-Managed Tablespace)[2]:
- 依赖数据字典表(UET$, FET$)记录区信息
- 分配/回收区需修改数据字典
- 易产生锁等待
- 易产生碎片
- 已废弃
本地管理表空间(LMT,Locally-Managed Tablespace)[2]:
- 依赖数据文件头的位图记录区信息
- 位图直接标记区状态
- 无字典争用,效率高
- 无外部碎片
- Oracle 10g+ 默认
查看区管理模式:
SELECT tablespace_name, extent_management, allocation_type
FROM dba_tablespaces;
-- EXTENT_MANAGEMENT: LOCAL(推荐)/ DICTIONARY(已废弃)
创建 LMT:
CREATE TABLESPACE users
DATAFILE '/u01/oradata/orcl/users01.dbf' SIZE 100M
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
6.2 段管理:MSSM vs ASSM
手动段空间管理(MSSM)[2]:
- 依赖**空闲列表(Free List)**跟踪空闲块
- 需手动设置
PCTFREE和PCTUSED - 高并发场景下空闲列表竞争
- 易产生碎片
自动段空间管理(ASSM)[2]:
- 依赖位图跟踪块状态(空闲、半满、全满)
- 自动管理块分配
- 无需 PCTUSED(PCTFREE 仍生效)
- 支持高并发
- 支持 Segment Shrink
- Oracle 10g+ 默认
查看段管理模式:
SELECT tablespace_name, segment_space_management
FROM dba_tablespaces;
-- SEGMENT_SPACE_MANAGEMENT: AUTO(推荐)/ MANUAL
创建 ASSM:
CREATE TABLESPACE app_data
DATAFILE '/u01/oradata/orcl/app_data01.dbf' SIZE 200M
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO;
7. 标准表空间
7.1 SYSTEM 表空间
- 存储数据字典(SYS 用户的表、视图)
- 包含所有 PL/SQL 存储过程源码
- 不可删除、不可脱机、不可只读
- 不要存放业务数据
SELECT file_name, bytes/1024/1024 AS size_mb
FROM dba_data_files
WHERE tablespace_name = 'SYSTEM';
7.2 SYSAUX 表空间
- 10g 引入,作为 SYSTEM 的辅助
- 存储 AWR、EM、Text、Spatial 等组件
- 不可删除,但可脱机
-- 查看 SYSAUX 占用者
SELECT occupant_name, space_usage_kbytes/1024 AS size_mb
FROM v$sysaux_occupants
ORDER BY space_usage_kbytes DESC;
7.3 UNDO 表空间
- 存储 Undo 数据
- 至少一个,可以有多个
- 详见 Oracle Undo 表空间与事务管理详解
7.4 TEMP 表空间
- 存储 SQL 排序、哈希连接的临时数据
- 至少一个
- 共享给所有用户使用
SELECT file_name, bytes/1024/1024 AS size_mb
FROM dba_temp_files;
-- 查看临时段使用情况
SELECT tablespace_name,
SUM(bytes_used)/1024/1024 AS used_mb,
SUM(bytes_free)/1024/1024 AS free_mb
FROM v$temp_space_header
GROUP BY tablespace_name;
7.5 USERS 表空间
- 默认用户表空间
- 创建用户时如未指定,使用此表空间
- 生产环境建议为每个业务创建独立表空间
8. 大文件表空间(Bigfile Tablespace)
10g 引入[1],单个数据文件最大可达 4G × block_size(8K 块即 32TB)。
特点:
- 单文件,简化管理
- 减少 Latch 争用
- 必须用 ASM 或 LMT + ASSM
创建:
CREATE BIGFILE TABLESPACE big_data
DATAFILE '/u01/oradata/orcl/big_data01.dbf' SIZE 100G
AUTOEXTEND ON NEXT 10G MAXSIZE 30T;
对比 Smallfile 和 Bigfile:
| 维度 | Smallfile | Bigfile |
|---|---|---|
| 单文件最大 | 4M 块(约 32GB) | 4G 块(约 32TB) |
| 每表空间文件数 | 多个 | 一个 |
| 管理 | 复杂 | 简单 |
| 备份 | 可并行 | 单文件 |
| 性能 | 多文件可分布 | 单文件 |
9. 表空间相关视图
9.1 dba_tablespaces
SELECT tablespace_name, contents, status,
extent_management, allocation_type,
segment_space_management, bigfile
FROM dba_tablespaces;
9.2 dba_data_files
SELECT file_name, file_id, tablespace_name,
bytes/1024/1024 AS size_mb,
autoextensible, maxbytes/1024/1024 AS max_mb,
increment_by * 8192 / 1024 / 1024 AS increment_mb
FROM dba_data_files
ORDER BY tablespace_name;
9.3 dba_free_space
-- 查看表空间剩余空间
SELECT tablespace_name,
SUM(bytes)/1024/1024 AS free_mb,
COUNT(*) AS free_extents
FROM dba_free_space
GROUP BY tablespace_name
ORDER BY free_mb;
9.4 dba_segments
-- 查看段
SELECT owner, segment_name, segment_type,
tablespace_name, bytes/1024/1024 AS size_mb
FROM dba_segments
WHERE tablespace_name = 'USERS'
ORDER BY bytes DESC;
9.5 v$tablespace
SELECT ts#, name, bigfile, included_in_database_backup
FROM v$tablespace;
9.6 综合查询:表空间使用情况
SELECT
a.tablespace_name,
a.total_mb,
NVL(b.used_mb, 0) AS used_mb,
NVL(b.used_mb, 0) / a.total_mb * 100 AS used_pct,
a.total_mb - NVL(b.used_mb, 0) AS free_mb
FROM (
SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb
FROM dba_data_files
GROUP BY tablespace_name
) a
LEFT JOIN (
SELECT tablespace_name, SUM(bytes)/1024/1024 AS used_mb
FROM dba_segments
GROUP BY tablespace_name
) b
ON a.tablespace_name = b.tablespace_name
ORDER BY used_pct DESC;
10. 表空间管理操作
10.1 创建表空间
-- 标准 OLTP 表空间
CREATE TABLESPACE business_data
DATAFILE '/u01/oradata/orcl/business01.dbf' SIZE 1G
AUTOEXTEND ON NEXT 100M MAXSIZE 10G
EXTENT MANAGEMENT LOCAL AUTOALLOCATE
SEGMENT SPACE MANAGEMENT AUTO;
-- 多数据文件
CREATE TABLESPACE big_data
DATAFILE
'/u01/oradata/orcl/big01.dbf' SIZE 5G,
'/u02/oradata/orcl/big02.dbf' SIZE 5G
AUTOEXTEND ON NEXT 500M MAXSIZE 50G
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
-- 加密表空间(需先建 keystore)
CREATE TABLESPACE encrypted_data
DATAFILE '/u01/oradata/orcl/enc01.dbf' SIZE 1G
ENCRYPTION USING 'AES256'
DEFAULT STORAGE (ENCRYPT);
10.2 修改表空间
-- 重命名
ALTER TABLESPACE users RENAME TO app_data;
-- 只读
ALTER TABLESPACE users READ ONLY;
-- 可读写
ALTER TABLESPACE users READ WRITE;
-- 脱机
ALTER TABLESPACE users OFFLINE NORMAL;
-- 联机
ALTER TABLESPACE users ONLINE;
10.3 删除表空间
-- 仅删除表空间(保留数据文件,不推荐)
DROP TABLESPACE users;
-- 删除表空间和数据文件(推荐)
DROP TABLESPACE users INCLUDING CONTENTS AND DATAFILES;
-- 同时删除约束
DROP TABLESPACE users INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;
坑 2:删除表空间前必须确认无依赖对象。
10.4 数据文件管理
-- 添加数据文件
ALTER TABLESPACE users
ADD DATAFILE '/u02/oradata/orcl/users02.dbf'
SIZE 500M
AUTOEXTEND ON NEXT 100M MAXSIZE 5G;
-- Bigfile 表空间 resize
ALTER TABLESPACE big_data RESIZE 200G;
-- 数据文件 resize
ALTER DATABASE DATAFILE '/u01/oradata/orcl/users01.dbf'
RESIZE 1G;
-- 数据文件自动扩展
ALTER DATABASE DATAFILE '/u01/oradata/orcl/users01.dbf'
AUTOEXTEND ON NEXT 100M MAXSIZE 5G;
-- 数据文件重命名(需表空间脱机)
ALTER TABLESPACE users OFFLINE NORMAL;
-- OS 层 mv
ALTER TABLESPACE users RENAME DATAFILE
'/u01/oradata/orcl/users01.dbf'
TO '/u02/oradata/orcl/users01.dbf';
ALTER TABLESPACE users ONLINE;
11. 空间管理与碎片
11.1 高水位线(HWM)
HWM 标记段中曾经被使用过的最高数据块位置[1]。
段空间布局:
┌───────────────────────────────────────┐
│ 已使用块 │ 未使用块(HWM 以下) │ HWM 以上未格式化
└───────────────────────────────────────┘
↑ HWM
全表扫描会扫描 HWM 以下所有块(即使空块)
查看 HWM:
-- 表的 HWM
SELECT table_name, blocks, empty_blocks, num_rows
FROM dba_tables
WHERE table_name = 'YOUR_TABLE';
-- 实际使用情况
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'EMP');
SELECT blocks, empty_blocks FROM dba_tables WHERE table_name='EMP';
坑 3:DELETE 数据不会降低 HWM,全表扫描仍扫描所有块。
11.2 段收缩(Segment Shrink)
收缩段可降低 HWM,回收空闲空间[2]:
-- 1. 启用行移动
ALTER TABLE scott.emp ENABLE ROW MOVEMENT;
-- 2. 收缩段(包含 HWM 调整)
ALTER TABLE scott.emp SHRINK SPACE;
-- 3. 仅整理碎片,不调整 HWM
ALTER TABLE scott.emp SHRINK SPACE COMPACT;
-- 4. 收缩并 CASCADE(含索引)
ALTER TABLE scott.emp SHRINK SPACE CASCADE;
-- 5. 重新收集统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'EMP');
坑 4:段收缩会触发行迁移,影响期间性能,建议低峰执行。
12. 常见坑与排错
坑 1:ORA-01653 表空间不足
现象:
ORA-01653: unable to extend table SCOTT.EMP by 128 in tablespace USERS
解决:
-- 1. 查看表空间剩余空间
SELECT tablespace_name, SUM(bytes)/1024/1024 AS free_mb
FROM dba_free_space
WHERE tablespace_name = 'USERS'
GROUP BY tablespace_name;
-- 2. 添加数据文件
ALTER TABLESPACE users
ADD DATAFILE '/u02/oradata/orcl/users02.dbf'
SIZE 1G AUTOEXTEND ON NEXT 100M MAXSIZE 10G;
-- 3. 或 resize 现有文件
ALTER DATABASE DATAFILE '...' RESIZE 2G;
-- 4. 或启用自动扩展
ALTER DATABASE DATAFILE '...' AUTOEXTEND ON;
坑 2:ORA-01652 临时表空间不足
现象:
ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
解决:
-- 添加临时文件
ALTER TABLESPACE temp
ADD TEMPFILE '/u02/oradata/orcl/temp02.dbf'
SIZE 2G AUTOEXTEND ON NEXT 100M MAXSIZE 10G;
坑 3:ORA-01688 表空间配额不足
现象:
ORA-01688: table SCOTT.EMP partition P1 extended failed
原因:用户在表空间的配额已用尽。
解决:
-- 查看用户配额
SELECT tablespace_name, bytes/1024/1024 AS used_mb,
max_bytes/1024/1024 AS max_mb
FROM dba_ts_quotas
WHERE username = 'SCOTT';
-- 增加配额
ALTER USER scott QUOTA UNLIMITED ON users;
坑 4:SYSTEM 表空间爆满
现象:SYSTEM 表空间使用率过高。
解决:
-- 查看 SYSTEM 表空间中的非系统对象
SELECT owner, segment_name, segment_type, bytes/1024/1024 AS size_mb
FROM dba_segments
WHERE tablespace_name = 'SYSTEM'
AND owner NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP')
ORDER BY bytes DESC;
-- 迁移到其他表空间
ALTER TABLE scott.emp MOVE TABLESPACE users;
ALTER INDEX scott.emp_pk REBUILD TABLESPACE users;
坑 5:表空间碎片严重
现象:表空间剩余空间足够,但仍报 ORA-01653。
诊断:
-- 查看碎片程度
SELECT tablespace_name,
COUNT(*) AS free_extents,
MAX(bytes)/1024/1024 AS max_free_mb,
SUM(bytes)/1024/1024 AS total_free_mb
FROM dba_free_space
GROUP BY tablespace_name;
-- free_extents 多但 max_free_mb 小 = 碎片严重
解决:
- 用 LMT + UNIFORM 避免碎片
- 段收缩
- 表空间重组(exp/imp 或 data pump)
坑 6:数据文件损坏
现象:
ORA-01115: IO error reading block from file (block # )
ORA-01110: data file 4: '/u01/oradata/orcl/users01.dbf'
解决:
-- 1. 查看损坏数据文件
SELECT file#, status, name FROM v$datafile WHERE file# = 4;
-- 2. 脱机
ALTER DATABASE DATAFILE 4 OFFLINE;
-- 3. RMAN 恢复
rman target /
RMAN> RESTORE DATAFILE 4;
RMAN> RECOVER DATAFILE 4;
-- 4. 联机
ALTER DATABASE DATAFILE 4 ONLINE;
坑 7:表空间 OFFLINE 后无法 ONLINE
现象:
ORA-01113: file 4 needs media recovery
解决:
-- 需要先恢复
RECOVER DATAFILE 4;
ALTER DATABASE DATAFILE 4 ONLINE;
坑 8:HWM 过高导致查询慢
现象:表数据不多,但查询慢。
诊断:
SELECT table_name, num_rows, blocks,
num_rows / NULLIF(blocks, 0) AS rows_per_block
FROM dba_tables
WHERE table_name = 'YOUR_TABLE';
-- rows_per_block 远小于正常值(通常 50-200)说明 HWM 过高
解决:
-- 段收缩
ALTER TABLE your_table ENABLE ROW MOVEMENT;
ALTER TABLE your_table SHRINK SPACE;
-- 或重建表
ALTER TABLE your_table MOVE TABLESPACE users;
13. 最佳实践
- 使用 LMT + ASSM:Oracle 10g+ 默认,避免碎片和并发问题[2]
- 业务数据独立表空间:避免放 SYSTEM
- 数据文件 AUTOEXTEND ON:避免 ORA-01653
- 设置 MAXSIZE:避免撑爆磁盘
- 数据文件分散在不同磁盘:I/O 负载均衡
- TEMP 表空间适当大:避免排序失败
- UNDO 表空间适当大:避免 ORA-01555
- 定期监控使用率:阈值 80%
- 生产环境避免 DMT:已废弃
- Bigfile 仅在超大表空间使用:单文件管理简单
- 段收缩降低 HWM:定期执行
- 批量加载后立即收集统计:避免 CBO 决策错误
- 表空间加密保护敏感数据:金融、医疗场景
- 大表用分区表:跨多个表空间
- SYSTEM 表空间只放系统对象:业务对象迁移出去
14. 参考资料
[1] Oracle Database 19c Concepts,Logical Storage Structures: https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/logical-storage-structures.html
[2] CSDN,《微观世界的层级之美:深度解析 Oracle 数据块、区(Extent)与段(Segment)的层级关系》: https://blog.csdn.net/qq_41840843/article/details/162770757
[3] CSDN,《深入探索 Oracle 数据库空间管理与监控》: https://blog.csdn.net/qq_36936192/article/details/155457150
[4] Oracle Database 19c Administrator’s Guide,Managing Tablespaces: https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-tablespaces.html
[5] Oracle Database 19c Concepts,Physical Storage Structures: https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/physical-storage-structures.html
[6] GBASE 数据库,《南大通用 GBase 8s 数据库与 Oracle 存储结构对照简析》: http://m.toutiao.com/group/7664867784794325538/
[7] Oracle Database 19c Administrator’s Guide,Bigfile Tablespaces: https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-tablespaces.html#GUID-3F8A6F3B-78D2-4D67-9F12-2B5B6F8B5E26
相关文章