数据库基础体系 · 第 106/139 篇。文章以各产品官方稳定版本的公开语义为准;示例会明确引擎、事务与部署边界。
Oracle 存储管理:Tablespace、Segment、Extent、Block 和 ASM
在 Oracle 中,一行数据从逻辑对象到物理存储,通常要经过这样一条链路:
表或索引
-> Segment
-> Extent
-> Oracle Block
-> Datafile
-> ASM File
-> ASM Disk Group
-> 物理磁盘或云块存储
这条链路描述的是不同层次的对象。Tablespace、Segment、Extent、Block 主要属于 Oracle 数据库存储模型;ASM 则是 Oracle 提供的卷管理和文件系统抽象,用来管理数据库文件所在的存储池。ASM 不会替代这些数据库逻辑概念,也不会把表直接“存进 ASM”。
一、先区分逻辑存储和物理存储
Oracle 存储模型可以分成两组概念。
1. 数据库逻辑层
| 对象 | 作用 |
|---|---|
| Tablespace | 数据库中的逻辑存储容器 |
| Segment | 某个表、索引、LOB 或其他对象实际使用的空间 |
| Extent | Segment 一次分配的一组连续数据块 |
| Block | Oracle 管理数据的最小 I/O 单位 |
2. 数据库文件和存储层
| 对象 | 作用 |
|---|---|
| Datafile | Tablespace 在操作系统或 ASM 中对应的数据文件 |
| Tempfile | 临时表空间使用的临时文件 |
| ASM Disk Group | ASM 管理的磁盘存储池 |
| ASM File | ASM 为数据库文件提供的文件抽象 |
| ASM Disk | ASM 使用的底层磁盘、分区、LUN 或其他设备 |
一个 Tablespace 可以包含一个或多个 Datafile;一个 Datafile 属于一个 Tablespace;一个 Segment 可以跨越多个 Datafile,但一个 Extent 不会跨越 Datafile。
因此,下面这些说法并不等价:
表属于某个 Tablespace
表占用了若干 Segment
Segment 占用了若干 Extent
Extent 使用了一组 Block
Block 位于某个 Datafile
Datafile 可能由 ASM 管理
二、Tablespace:数据库的逻辑存储容器
Tablespace 是 Oracle 用来组织数据文件和数据库对象的逻辑结构。表、索引、Undo、临时对象等都需要在某个 Tablespace 中分配空间。
创建普通永久 Tablespace 的一个示例是:
CREATE TABLESPACE app_data
DATAFILE '/u01/oradata/DB01/app_data01.dbf'
SIZE 100M
AUTOEXTEND ON
NEXT 10M
MAXSIZE 1G
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO;
这个命令包含几个不同层次的配置:
app_data是 Tablespace 名称。DATAFILE指定实际数据文件。SIZE 100M指定数据文件初始大小。AUTOEXTEND ON允许数据文件自动增长。NEXT 10M指定每次自动扩展的增量。MAXSIZE 1G限制自动扩展上限。EXTENT MANAGEMENT LOCAL表示 Extent 的空闲状态由 Tablespace 内部位图管理。SEGMENT SPACE MANAGEMENT AUTO表示使用 ASSM,即 Automatic Segment Space Management。
生产环境通常优先使用 locally managed tablespace。Dictionary-managed tablespace 属于较早的管理方式,在现代数据库设计中通常不应作为新建对象的默认选择。
1. Tablespace 不等于 Datafile
下面的查询可以查看 Tablespace 和 Datafile 的关系:
SELECT
tablespace_name,
file_id,
file_name,
bytes,
autoextensible,
maxbytes
FROM dba_data_files
ORDER BY tablespace_name, file_id;
可能得到类似结果:
TABLESPACE_NAME FILE_ID FILE_NAME BYTES AUTOEXTENSIBLE MAXBYTES
--------------- ------- -------------------------------- ------ -------------- --------
APP_DATA 7 /u01/oradata/DB01/app_data01.dbf 104857600 YES 1073741824
这里:
- Tablespace 的大小通常是其 Datafile 大小之和;
- Datafile 的自动扩展上限不一定等于文件当前大小;
- Datafile 文件存在,并不代表其中已经有表或索引;
- Tablespace 空间足够,也不代表某个 Segment 一定能立即分配空间,因为还要受到文件上限、数据文件可用空间、配额和其他约束影响。
可以把 Tablespace 看成数据库的逻辑地址空间,而 Datafile 是这个地址空间的物理承载文件。
2. Smallfile 和 Bigfile Tablespace
Oracle 支持两类主要 Tablespace 文件组织方式:
- Smallfile tablespace:可以包含多个 Datafile;
- Bigfile tablespace:通常只有一个很大的 Datafile。
Bigfile tablespace 简化了文件数量管理,但单个文件的容量、备份、恢复和底层存储能力需要单独评估。它不是“自动拥有更多空间”,而是改变了 Tablespace 到 Datafile 的组织方式。
3. 永久、临时和 Undo Tablespace
不同 Tablespace 的空间语义并不完全相同:
- 永久 Tablespace 保存表、索引等持久对象;
- 临时 Tablespace 保存排序、哈希连接、临时表等操作产生的临时段;
- Undo Tablespace 保存 Undo Segment,用于事务回滚、读一致性和闪回相关机制。
临时空间不足时,常见错误是 ORA-01652: unable to extend temp segment。这不一定说明永久表空间不足,而可能是某个排序或连接操作需要更多临时空间。
永久 Tablespace 空间不足时,常见错误是:
ORA-01653: unable to extend table ...
ORA-01654: unable to extend index ...
这些错误说明对应 Segment 需要获得新的 Extent,但 Tablespace 无法满足分配请求。
三、Block:Oracle 管理数据的最小单位
Oracle Block 是 Oracle 数据库执行数据读写时使用的基本单位。一个 Block 通常对应 Datafile 中一段固定大小的连续字节。
数据库的标准 Block 大小由初始化参数 DB_BLOCK_SIZE 决定,常见值是 8 KB。Oracle 也支持在满足条件时配置多个 Block Size,例如使用 2 KB、4 KB、8 KB、16 KB 或 32 KB 的 Tablespace Block Size,但不同 Block Size 需要对应的 Buffer Cache 配置。
可以查看数据库 Block Size:
SELECT name, value
FROM v$parameter
WHERE name IN ('db_block_size', 'db_cache_size');
查看各 Tablespace 的 Block Size:
SELECT
tablespace_name,
block_size,
extent_management,
segment_space_management
FROM dba_tablespaces
ORDER BY tablespace_name;
1. Block 的容量计算
如果某个 Tablespace 的 Block Size 是 8 KB,一个 1 MB 的 Extent 理论上包含:
因此,1 MB Extent 在 8 KB Block 的 Tablespace 中通常对应 128 个 Block。
这是空间换算关系,不代表每个 Block 都能存放:
条记录。因为 Block 还需要容纳 Block Header、行目录、事务槽、空闲空间,以及行迁移、变长列等额外结构。
2. Block 的内部结构
一个普通数据 Block 通常包含:
+----------------------+
| Block Header |
+----------------------+
| Table Directory |
+----------------------+
| Row Directory |
+----------------------+
| Free Space |
+----------------------+
| Row Data |
+----------------------+
其中:
- Block Header 保存 Block 管理信息;
- Table Directory 用于标识该 Block 中涉及的表;
- Row Directory 保存行的位置指针;
- Free Space 用于插入新行、行增长和事务相关结构;
- Row Data 保存实际行数据。
Block 的剩余空间并不全部可以用于行数据。PCTFREE 控制 Block 预留多少空间用于已有行的后续更新。例如:
CREATE TABLE orders (
order_id NUMBER PRIMARY KEY,
note VARCHAR2(4000)
)
PCTFREE 20;
PCTFREE 20 的含义不是“永远浪费 20% 空间”,而是当 Block 用于插入时,Oracle 会尽量保留一部分空间,避免后续更新行时没有空间。实际行为还会受到行大小、更新方式和段空间管理机制影响。
3. Block 与并发
多个会话可能同时访问同一个 Block。Oracle 在 Block 中维护事务相关信息,例如 ITL(Interested Transaction List),以记录哪些事务正在修改该 Block 中的行。
当并发事务很多,而 Block 中可用的 ITL 槽不足时,可能出现与事务槽扩展或并发等待相关的问题。对于 ASSM Tablespace,可以通过 INITRANS 等属性影响初始事务槽配置,但不能把 INITRANS 简单理解成“允许的最大并发事务数”。
Oracle 的行级锁最终也需要在 Block 的数据结构中体现。锁的是行,而不是通常意义上的整张表或整个数据文件;但多个热点行集中在少数 Block 上时,仍可能形成 Block 级别的并发争用。
4. HWM 与 Block
Segment 会记录高水位线(High Water Mark,HWM)。HWM 表示该 Segment 曾经扩展到的边界。
例如:
- 表初始分配 100 个 Block;
- 插入数据,使用其中 20 个 Block;
- 删除全部数据;
- Segment 仍可能保留 100 个 Block,HWM 也不会因为普通
DELETE自动回退。
因此,下面两种“空间”不同:
- Segment 已经分配给表的空间;
- Segment 内当前可以再次使用的空闲空间。
执行普通全表扫描时,Oracle 通常需要检查 HWM 以下的 Block,即使其中很多 Block 已经没有有效行。DELETE 释放的空间可以被该 Segment 后续使用,但通常不会自动返还给 Tablespace。
可以通过 TRUNCATE、Segment Shrink 或重组等方式改变空间状态,但这些操作的锁、ROWID、索引、UNDO 和业务影响不同,不能只按“释放空间”理解。
四、Extent:Segment 一次获得的一组 Block
Extent 是 Segment 向 Tablespace 申请空间时一次获得的一组连续 Oracle Block。它是 Segment 和 Block 之间的分配单位。
如果:
- Block Size = 8 KB;
- Extent = 1 MB;
那么一个 Extent 包含 128 个 Block。某个 Segment 分配了 10 个这样的 Extent,则其理论分配空间为:
对应:
查询 Segment 的 Extent:
SELECT
owner,
segment_name,
segment_type,
tablespace_name,
extent_id,
file_id,
block_id,
blocks,
bytes
FROM dba_extents
WHERE owner = 'APP'
AND segment_name = 'ORDERS'
ORDER BY extent_id;
字段含义包括:
EXTENT_ID:该 Segment 内 Extent 的编号;FILE_ID:Extent 所在 Datafile 的文件编号;BLOCK_ID:Extent 起始 Block;BLOCKS:Extent 包含的 Block 数;BYTES:Extent 大小。
1. Extent 不一定连续覆盖整个 Segment
一个 Segment 的多个 Extent 可以位于:
- 同一个 Datafile 的不同区域;
- 同一个 Tablespace 的不同 Datafile;
- 由于历史增长和空间回收而分散的位置。
但一个 Extent 本身位于单个 Datafile 中,并表示该文件内一段连续的 Oracle Block。
因此,“表的数据在磁盘上连续”通常是不正确的。即使 Extent 在 Datafile 内连续,也不能直接推断底层磁盘上的物理扇区一定连续,特别是在 ASM、RAID、存储虚拟化或云块存储环境中。
2. Extent 的分配策略
Locally managed tablespace 主要有两种常见 Extent 分配策略:
CREATE TABLESPACE uniform_demo
DATAFILE '/u01/oradata/DB01/uniform_demo01.dbf'
SIZE 100M
EXTENT MANAGEMENT LOCAL
UNIFORM SIZE 1M;
UNIFORM SIZE 1M 表示该 Tablespace 中的 Extent 使用统一大小。
另一种是:
CREATE TABLESPACE auto_demo
DATAFILE '/u01/oradata/DB01/auto_demo01.dbf'
SIZE 100M
EXTENT MANAGEMENT LOCAL
AUTOALLOCATE;
AUTOALLOCATE 由 Oracle 根据 Segment 的增长阶段选择 Extent 大小。它不保证所有 Extent 大小相同,也不应假设每次分配都严格等于对象定义中的 NEXT 值。
NEXT 等存储参数在现代 locally managed tablespace 和自动分配策略下,不能简单视为“下一次一定分配这么多字节”。实际大小还受到 Tablespace 的分配策略、Segment 类型和版本实现影响。
3. Segment 与 Extent 的实际示例
下面示例假设:
- 使用 Oracle 数据库;
- 当前用户具有创建 Tablespace、用户和对象的权限;
- 数据文件路径
/u01/oradata/DB01/已存在且 Oracle 进程有权限访问; - 这是文件系统部署,不是 ASM 部署。
CREATE TABLESPACE lab_data
DATAFILE '/u01/oradata/DB01/lab_data01.dbf'
SIZE 20M
AUTOEXTEND ON
NEXT 5M
MAXSIZE 100M
EXTENT MANAGEMENT LOCAL
AUTOALLOCATE
SEGMENT SPACE MANAGEMENT AUTO;
CREATE USER lab IDENTIFIED BY "StrongPassword_1"
DEFAULT TABLESPACE lab_data
QUOTA 50M ON lab_data;
GRANT CREATE SESSION, CREATE TABLE TO lab;
CONN lab/"StrongPassword_1"
CREATE TABLE t_demo (
id NUMBER PRIMARY KEY,
text VARCHAR2(100)
);
INSERT INTO t_demo
SELECT level, RPAD('x', 100, 'x')
FROM dual
CONNECT BY level <= 10000;
COMMIT;
随后以具有数据字典查询权限的用户检查:
SELECT
segment_name,
segment_type,
tablespace_name,
bytes,
blocks,
extents
FROM dba_segments
WHERE owner = 'LAB'
AND segment_name IN ('T_DEMO', 'SYS_C0012345');
实际约束名可能不同,因此主键索引名称最好通过以下查询确认:
SELECT index_name, table_name
FROM dba_indexes
WHERE owner = 'LAB'
AND table_name = 'T_DEMO';
再查看表的 Extent:
SELECT
segment_name,
extent_id,
file_id,
block_id,
blocks,
bytes
FROM dba_extents
WHERE owner = 'LAB'
AND segment_name = 'T_DEMO'
ORDER BY extent_id;
这个过程说明:
- 创建表时,Oracle 创建的是表对象定义;
- 在启用 deferred segment creation 的环境中,空表可能暂时没有分配表 Segment;
- 插入第一批数据或显式分配空间后,表 Segment 才会产生;
- 表增长时,Oracle 从
LAB_DATA的空闲空间中分配 Extent; - Extent 再由多个 Block 组成;
- 主键还会产生一个独立的索引 Segment。
“一个表对应一个 Segment”也不是绝对规律:
- 分区表通常每个分区有独立 Segment;
- 分区索引可能每个分区有独立 Segment;
- LOB 列通常会产生独立的 LOB Segment 和索引 Segment;
- 临时对象和 Undo 对象有自己的 Segment 生命周期;
- 空表可能只有对象元数据而尚未分配 Segment。
五、Segment:对象实际使用空间的边界
Segment 是 Oracle 为某类数据库对象分配的一组 Extent。它描述的是“某个对象已经获得的空间”,而不是对象的全部逻辑定义。
常见 Segment 类型包括:
- TABLE:普通堆表;
- INDEX:索引;
- TABLE PARTITION:表分区;
- INDEX PARTITION:索引分区;
- LOBSEGMENT:LOB 数据;
- LOBINDEX:LOB 索引;
- UNDO:Undo 段;
- TEMPORARY:临时段。
查询用户 Segment:
SELECT
owner,
segment_name,
partition_name,
segment_type,
tablespace_name,
bytes,
blocks,
extents
FROM dba_segments
WHERE owner = 'APP'
ORDER BY bytes DESC;
需要注意:
DBA_SEGMENTS.BYTES
表示 Segment 已分配的空间,不等于有效行数据的字节数,也不等于查询结果中所有列的逻辑长度之和。
例如,一个表可能有:
- 大量删除后留下的 Segment 空间;
PCTFREE预留空间;- 行迁移产生的额外空间;
- LOB 数据存储在独立 Segment;
- 索引 Segment 大于表中的某些有效数据量。
1. Segment 空间和 Tablespace 空闲空间
Tablespace 空闲空间是“尚未分配给 Segment 的空间”。
Segment 内部空闲空间是“已经属于该 Segment,但目前没有存放有效行或索引条目的空间”。
二者不能混淆:
Tablespace Free Space
= 可以分配给新的或增长中的 Segment 的空间
Segment Free Space
= 已归某个 Segment 所有、可由该 Segment 重用的空间
执行 DELETE 通常只增加 Segment 内部可重用空间,不会直接增加 Tablespace 空闲空间。
检查 Tablespace 文件和空闲空间:
SELECT
tablespace_name,
SUM(bytes) AS free_bytes
FROM dba_free_space
GROUP BY tablespace_name
ORDER BY tablespace_name;
在 ASSM Tablespace 中,可以进一步使用 DBMS_SPACE 分析 Segment 内部空间,但该接口需要适当权限,并且不同 Segment 类型支持的分析方式存在差异。不能仅通过 DBA_SEGMENTS.BYTES 判断表内有多少空间真正可插入。
六、ASM:为数据库文件提供存储池和文件管理
ASM(Automatic Storage Management)是 Oracle 提供的存储管理组件。它位于数据库文件和底层存储设备之间,主要负责:
- 将多个磁盘组织成 Disk Group;
- 为数据库文件提供文件抽象;
- 对数据进行条带化;
- 在配置了镜像冗余时提供 ASM 层面的镜像;
- 通过重新平衡在磁盘加入、移除或容量变化后迁移数据;
- 管理 ASM 文件元数据和空间分配。
ASM 不是数据库 Buffer Cache,也不是 SQL 层面的表空间管理器。
1. ASM 的层次
数据库文件
-> ASM File
-> ASM Disk Group
-> ASM Disk
-> 底层存储设备
例如,一个数据文件可能被写成:
CREATE TABLESPACE asm_data
DATAFILE '+DATA'
SIZE 1G
AUTOEXTEND ON
NEXT 100M
MAXSIZE 10G
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO;
这里的 +DATA 是 ASM Disk Group 名称。Oracle 会在该 Disk Group 中创建和管理实际 ASM 文件。用户不需要提供传统操作系统路径。
也可以使用别名:
+DATA/DB01/DATAFILE/ASM_DATA.123.987654321
这类名称表达的是 ASM 文件位置和标识,不是普通文件系统中的目录路径。
2. ASM Disk Group 和冗余
ASM Disk Group 把多个 ASM Disk 组成一个存储池。Disk Group 创建时可以指定冗余策略,例如:
- External redundancy:由外部存储系统提供镜像;
- Normal redundancy:由 ASM 提供相应镜像;
- High redundancy:提供更高等级的 ASM 镜像保护。
选择时必须明确“谁负责冗余”:
ASM 冗余 + 存储阵列冗余
不一定比单独一种冗余更合理,可能增加容量消耗和管理复杂度。反过来,External redundancy 也不是“没有保护”,它表示保护责任交给底层存储系统。
可以查看 ASM Disk Group:
SELECT
name,
state,
type,
total_mb,
free_mb,
required_mirror_free_mb,
usable_file_mb
FROM v$asm_diskgroup;
几个字段不能混为一谈:
TOTAL_MB:Disk Group 总容量;FREE_MB:未分配空间;REQUIRED_MIRROR_FREE_MB:为维持镜像和故障恢复所需保留的空间;USABLE_FILE_MB:考虑冗余和镜像要求后,数据库文件实际可以安全使用的估算空间。
因此,FREE_MB 并不总是等于“还能创建多少可用数据文件空间”。
3. ASM Allocation Unit 与 Oracle Extent
ASM 也有自己的分配单位,称为 Allocation Unit(AU)。Oracle 数据库还有自己的 Extent。二者属于不同层次:
Oracle Segment
-> Oracle Extent
-> Oracle Block
Oracle Datafile
-> ASM File
-> ASM Extent / Allocation Unit
-> ASM Disk
不要因为两者都使用“extent”这个词,就认为它们是同一个对象。
- Oracle Extent 面向数据库对象空间;
- ASM 文件分配面向存储池空间;
- Oracle Block 是数据库访问单位;
- ASM AU 是 ASM 管理空间和条带化的单位。
Oracle 通过 Datafile 把数据库 Block 的逻辑地址映射到 ASM 文件。一个数据库进程只需要访问某个 Datafile 的某个 Block,不需要直接知道该 Block 最终落在哪块 ASM Disk 上。
4. ASM 条带化与数据库 I/O
ASM 可以把文件数据分散到多个磁盘上,以获得并行 I/O。常见概念包括:
- coarse striping:较大的条带单位;
- fine striping:较小的条带单位,适用于对低延迟和并发 I/O 有特殊要求的文件类型。
条带化的目标是改善 I/O 分布,不意味着每个 SQL 查询都会自动获得线性性能提升。实际效果还取决于:
- SQL 是否产生足够的并发 I/O;
- Buffer Cache 命中率;
- 存储阵列或云存储的吞吐限制;
- 数据文件布局;
- RAC 实例之间的访问模式;
- I/O 调度和底层设备队列。
ASM 不能修复错误的索引设计、全表扫描、过小的内存配置或存储设备本身的性能瓶颈。
5. ASM Rebalance
当 ASM Disk Group 中加入或移除磁盘时,ASM 可以执行 Rebalance,把文件数据重新分布到新的磁盘集合中。
典型状态变化是:
磁盘加入
-> ASM 更新 Disk Group 元数据
-> 产生重新平衡操作
-> 数据块逐步迁移
-> 新旧磁盘分布趋于均衡
可以查看操作:
SELECT
group_number,
operation,
state,
power,
sofar,
est_work,
est_minutes
FROM v$asm_operation;
Rebalance 不是瞬时操作。提高 POWER 通常会增加后台迁移工作的资源使用,但具体影响取决于版本、存储设备和当前 I/O 负载。生产环境需要结合业务负载观察,而不能只根据一个固定数值判断安全与否。
七、从 SQL 到磁盘:一次数据访问经过什么路径
以查询某一行数据为例,逻辑过程可以简化为:
SQL 解析和执行
-> 根据表或索引定位 RowID
-> RowID 指向 Datafile 和 Block
-> 检查 Buffer Cache
-> 未命中时发起物理读
-> 访问 ASM 文件
-> ASM 将文件偏移映射到 AU 和底层磁盘
-> 数据返回 Buffer Cache
-> SQL 引擎读取行
RowID 通常包含对象、数据文件相对编号和 Block 等定位信息。可以用 DBMS_ROWID 查看普通堆表 RowID 的部分信息:
SELECT
rowid,
DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) AS relative_file_no,
DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) AS block_no
FROM app.orders
WHERE order_id = 1001;
这个示例需要满足:
- 查询的是支持这种 RowID 解释方式的普通堆表;
- 当前用户有执行
DBMS_ROWID的权限; - 分区表、索引组织表、迁移行等场景需要额外考虑。
RowID 是行的物理定位信息,不应当被当作永久业务主键。表移动、分区维护、Segment 重组等操作可能改变 RowID。
八、Block、Extent、Segment 与 ASM 的边界
下面这个例子可以说明各层的职责:
表 ORDERS
-> ORDERS 表 Segment
-> Extent 0
-> Block 1000 ~ 1127
-> Extent 1
-> Block 5300 ~ 5427
-> Datafile 7
-> ASM File +DATA/...
-> ASM AU 分布在多个 ASM Disk
这里:
ORDERS是逻辑表;- 表 Segment 负责保存表数据;
- Extent 0 和 Extent 1 是 Segment 的两次空间分配;
- 每个 Extent 包含一组 Oracle Block;
- 两个 Extent 可以在 Datafile 中相距很远;
- Datafile 可能是 ASM File;
- ASM 决定 ASM 文件内容如何映射到 Disk Group;
- SQL 层不需要直接操作 ASM Disk。
因此,优化或诊断时必须先确定问题位于哪一层:
| 现象 | 可能相关层次 |
|---|---|
| 表空间满 | Tablespace、Datafile、ASM Disk Group |
| 表增长失败 | Segment、Extent、配额、Datafile |
| 全表扫描慢 | Block、HWM、Buffer Cache、I/O |
| 热点块争用 | Block、ITL、并发访问 |
| ASM 空间不足 | Disk Group 冗余、AU、Rebalance |
| 数据文件丢失 | Datafile、ASM、RMAN、Data Guard |
| RAC 跨实例访问代价高 | Buffer Cache、Cache Fusion、ASM 共享存储 |
九、常见误解与失败表现
1. “删除数据后 Tablespace 空间就增加了”
通常不成立。
DELETE FROM app.orders;
COMMIT;
这通常只让表 Segment 内的 Block 变得可重用,不会自动降低 DBA_SEGMENTS.BYTES,也不会直接增加 DBA_FREE_SPACE。
如果业务确实需要把空间还给 Tablespace,需要根据对象类型和业务窗口评估 TRUNCATE、SHRINK SPACE、移动 Segment 或重建对象等方案。
2. “AUTOEXTEND ON 说明空间不会耗尽”
不成立。自动扩展仍然受以下因素限制:
MAXSIZE;- 文件系统或 ASM Disk Group 容量;
- ASM 冗余后的可用容量;
- 数据库或用户配额;
- 存储设备故障;
- 数据文件最大尺寸;
- 实例和数据库配置。
因此要同时检查:
SELECT
tablespace_name,
file_name,
bytes,
maxbytes,
autoextensible
FROM dba_data_files;
SELECT
tablespace_name,
SUM(bytes) AS free_bytes
FROM dba_free_space
GROUP BY tablespace_name;
ASM 部署还要检查:
SELECT
name,
state,
type,
total_mb,
free_mb,
usable_file_mb
FROM v$asm_diskgroup;
3. “Extent 是物理磁盘上的连续区域”
不成立。
Extent 只是在 Oracle Datafile 层面由一组连续 Block 组成。Datafile 可能位于 ASM、RAID、LVM、存储阵列或虚拟化存储上,数据库无法也不应该把 Extent 直接等同于底层磁盘连续区间。
4. “ASM 就是 RAID”
不完全正确。
ASM 提供条带化、镜像和存储池管理,但它的冗余语义、故障域和恢复行为与传统 RAID 并不完全相同。使用 External redundancy 时,ASM 假设底层存储负责数据保护;使用 ASM redundancy 时,镜像由 ASM 管理。
5. “Tablespace 有空闲空间,任何表都能立即扩展”
不一定。
还需要考虑:
- 空闲空间是否位于合适的 Datafile;
- Datafile 是否达到上限;
- 用户是否有 Tablespace quota;
- Segment 的 Extent 分配策略;
- 临时表空间或 Undo 表空间的特殊语义;
- ASM Disk Group 是否有满足冗余要求的可用空间。
十、故障路径和恢复边界
Tablespace、Datafile 和 ASM 的故障恢复责任不同。
1. Datafile 损坏或丢失
数据库可能报告数据文件不可访问、块损坏或无法扩展。恢复通常涉及:
- RMAN 从备份恢复 Datafile;
- 使用归档日志和在线重做日志进行介质恢复;
- 如果有 Data Guard,可能从备用库获取对应保护;
- 如果是 ASM 故障,还要判断是单盘、磁盘组、路径还是底层存储故障。
ASM 镜像主要解决部分存储故障可用性问题,不等于数据库备份。误删表、错误更新、逻辑损坏通常不能依靠 ASM 镜像恢复到历史业务状态,仍需要 RMAN、闪回或其他逻辑恢复手段。
2. RAC 与 ASM
RAC 中多个数据库实例可以共享同一个 ASM Disk Group。ASM 负责共享存储和文件管理;RAC 实例之间的数据块缓存一致性由 Cache Fusion 等数据库集群机制负责。
因此:
ASM 解决“多个实例如何看到数据库文件”
RAC 解决“多个实例如何共同访问并协调数据库”
ASM 本身不能替代 RAC 的锁管理和缓存一致性机制。
3. Data Guard 与 ASM
Data Guard 负责主库和备用库之间的日志传输、应用和角色切换。主库和备用库都可以使用 ASM,但两者的 ASM Disk Group 通常属于各自主机或存储环境。
因此:
ASM:单个数据库环境中的文件和磁盘管理
Data Guard:数据库副本之间的灾难恢复和高可用
RMAN:备份、恢复和介质恢复
它们可以组合使用,但职责不同。
十一、诊断时应按层次逐步定位
遇到“空间不足”或“对象增长失败”时,可以按以下顺序检查,而不是直接扩容。
第一步:确认 Tablespace 类型和 Block Size
SELECT
tablespace_name,
status,
contents,
extent_management,
allocation_type,
segment_space_management,
block_size
FROM dba_tablespaces
WHERE tablespace_name = 'APP_DATA';
第二步:确认 Datafile 当前大小和上限
SELECT
file_id,
file_name,
bytes / 1024 / 1024 AS current_mb,
maxbytes / 1024 / 1024 AS max_mb,
autoextensible
FROM dba_data_files
WHERE tablespace_name = 'APP_DATA';
第三步:确认空闲空间和最大空闲区
SELECT
tablespace_name,
SUM(bytes) / 1024 / 1024 AS free_mb,
MAX(bytes) / 1024 / 1024 AS largest_free_extent_mb
FROM dba_free_space
WHERE tablespace_name = 'APP_DATA'
GROUP BY tablespace_name;
Locally managed tablespace 下,传统意义上的碎片问题与旧式字典管理不同,但“总空闲空间足够”仍不必然意味着某次具体分配一定成功,因为文件上限、配额和分配边界仍然存在。
第四步:确认哪个 Segment 在增长
SELECT
owner,
segment_name,
segment_type,
bytes / 1024 / 1024 AS allocated_mb,
extents
FROM dba_segments
WHERE tablespace_name = 'APP_DATA'
ORDER BY bytes DESC;
第五步:ASM 部署检查 Disk Group
SELECT
name,
state,
type,
total_mb,
free_mb,
usable_file_mb
FROM v$asm_diskgroup
ORDER BY name;
如果发现 ASM 正在 Rebalance,还应查看:
SELECT *
FROM v$asm_operation;
这样可以区分:
数据库对象空间增长问题
Tablespace/Datafile 容量问题
ASM Disk Group 可用空间问题
底层存储或路径故障
十二、一个完整的空间推导例子
假设某个 Tablespace:
- Block Size 为 8 KB;
- 一个表 Segment 已分配 64 个 Extent;
- 每个 Extent 为 4 MB;
- 其中有效数据约占已分配 Block 的 55%。
则:
1. 已分配空间
2. 每个 Extent 的 Block 数
3. Segment 的 Block 总数
4. 估算有效数据占用
但这个 140.8 MB 只是估算的有效数据比例,不能直接当作 Oracle 的精确“数据大小”。精确分析还需要考虑:
- Block Header;
- 行目录;
- PCTFREE;
- 行迁移和行链接;
- 事务槽;
- 变长列;
- LOB 外置存储;
- 索引单独占用的 Segment;
- 空间回收和重用状态。
这个例子最重要的结论不是某个百分比,而是:
Segment 已分配空间
≠ 有效行数据大小
≠ 表逻辑列长度之和
≠ Tablespace 当前剩余空间
结语
Oracle 存储管理的核心是把不同层次准确对应起来:
Tablespace:逻辑容器
Segment:对象已经获得的空间
Extent:Segment 一次分配的一组 Block
Block:Oracle 访问和管理数据的基本单位
Datafile:Tablespace 的数据库文件承载
ASM:管理数据库文件所在存储池和底层映射
当对象增长、空间耗尽、I/O 变慢或存储发生故障时,只有先确定问题位于哪一层,才能选择正确的处理方式。扩展 Datafile、回收 Segment 空间、增加 ASM 磁盘、调整 Block 或处理 RMAN/Data Guard 故障,解决的是完全不同的问题。
系列导航与关联阅读
- 系列入口:数据库完整学习路线:从关系模型、事务索引到分布式与向量检索
- 上一篇:Oracle Schema 与数据类型:NUMBER、字符、日期、LOB 和对象
- 下一篇:Oracle Redo、归档与 Checkpoint:提交、恢复和写入路径
- 延伸:Oracle 数据库架构:Instance、SGA、PGA、数据文件与后台进程
- 延伸:Oracle RMAN、Data Guard 与 RAC:备份恢复和高可用边界
官方资料
本文依据数据库官方文档重新梳理;正文、示例与生产检查清单由 WR BLOG 编写。

评论
0 条讨论