知识库✳

教程与手册

全部教程
  1. 01Oracle 函数手册
  2. 02性能优化手册
  3. 03Linux Shell
  4. 04Oracle 学习与演练
  5. 05网络基础学习
  6. 06数据治理与管理
返回个人网站
甲Oracle 学习教程从 SQL 到 PL/SQL 与运维
首页课程目录搜索演练场
知识库

已完成 0 / 22 章

模块一 · 入门与准备

  • 01Oracle 数据库体系结构
  • 02环境安装与连接方式
  • 03SQL*Plus 与常用工具

模块二 · SQL 查询基础

  • 04SELECT 查询基础
  • 05过滤与排序
  • 06单行函数
  • 07多表连接
  • 08分组聚合与 HAVING
  • 09子查询

模块三 · 数据与对象

  • 10DML 与事务控制
  • 11表与数据类型
  • 12约束
  • 13索引与执行计划
  • 14视图、序列与同义词

模块四 · PL/SQL 编程

  • 15PL/SQL 块与变量
  • 16流程控制与游标
  • 17存储过程与函数
  • 18触发器
  • 19异常处理

模块五 · 运维与进阶

  • 20用户与权限管理
  • 21表空间与存储管理
  • 22备份与恢复
❖

Oracle 学习教程

返回个人网站知识库

示例代码基于 Oracle AI Database 26ai / 23ai,查询示例使用官方 HR 示例方案。

以 Next.js 16 · Tailwind CSS v4 · HeroUI v3 装帧

21
  1. 首页
  2. 课程目录
  3. 表空间与存储管理

第 21 章◆高级◆建议 45 分钟◆模块五 · 运维与进阶

表空间与存储管理

理解逻辑存储层次,会创建表空间、添加数据文件、处理空间不足。

学完这一章,你应该能

  • 会创建表空间与数据文件
  • 能查看空间使用情况并扩容
  • 理解段、区、块与自动段空间管理
  • 知道 ORA-01652 该怎么处理

21.1创建表空间

  • EXTENT MANAGEMENT LOCAL 是 9i 之后的默认且推荐方式
  • SEGMENT SPACE MANAGEMENT AUTO 用位图管理,比手动管理更高效
  • AUTOEXTEND 要设 MAXSIZE,否则可能把磁盘写满导致实例挂起
  • 本地管理的表空间用 AUTOALLOCATE(由系统决定区大小)或 UNIFORM(所有区统一大小)管理区;只有 UNIFORM 才需要你指定统一的区大小
两种常见类型
-- 小文件表空间(默认类型,可包含多个数据文件)
CREATE TABLESPACE app_data
  DATAFILE 'app_data01.dbf'
  SIZE 100M
  AUTOEXTEND ON NEXT 50M MAXSIZE 2G
  EXTENT MANAGEMENT LOCAL      -- 本地管理,现代默认
  SEGMENT SPACE MANAGEMENT AUTO;
  -- 自动段空间管理

-- 大文件表空间:只能有 1 个数据文件,但该文件可以极大
-- 8KB 块下单文件上限约 32TB(2^32 个块)
CREATE BIGFILE TABLESPACE app_big
  DATAFILE 'app_big01.dbf'
  SIZE 1G
  AUTOEXTEND ON NEXT 100M;

CREATE TABLESPACE 需要 DBA 权限,普通用户执行会报 ORA-01031。另外 DATAFILE 只写裸文件名时,实际路径由初始化参数 DB_CREATE_FILE_DEST 决定(OMF);没配这个参数就必须写完整路径。后续要 RESIZE 时,路径必须与控制文件里登记的一致。

只作示例阅读:建/改用户、角色、表空间。请在独立学习数据库中练习。

21.2查看空间使用

表空间使用率
SELECT d.tablespace_name,
       ROUND(d.total_mb, 2)                                  AS total_mb,
       ROUND(NVL(f.free_mb, 0), 2)                           AS free_mb,
       ROUND(d.total_mb - NVL(f.free_mb, 0), 2)              AS used_mb,
       ROUND((d.total_mb - NVL(f.free_mb, 0)) / d.total_mb * 100, 2) AS used_pct
FROM   (SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb
        FROM   dba_data_files GROUP BY tablespace_name) d
LEFT   JOIN (SELECT tablespace_name, SUM(bytes)/1024/1024 AS free_mb
             FROM   dba_free_space GROUP BY tablespace_name) f
       ON f.tablespace_name = d.tablespace_name
ORDER  BY used_pct DESC;

只作示例阅读:读取全库字典或会话(沙箱只开放自身对象)。请在独立学习数据库中练习。

谁最占空间
SELECT owner, segment_name, segment_type,
       ROUND(bytes/1024/1024, 2) AS mb
FROM   dba_segments
WHERE  tablespace_name = 'USERS'
ORDER  BY bytes DESC
FETCH  FIRST 15 ROWS ONLY;

只作示例阅读:读取全库字典或会话(沙箱只开放自身对象)。请在独立学习数据库中练习。

21.3扩容与常见报错

  • ORA-01652: unable to extend ... → 某个段无法在指定表空间内扩展。segment_type 可能是 temporary、table、index、LOB 等,永久表空间不足同样会报这个错
  • ORA-01653: unable to extend table → 表无法在表空间内扩展,通常是表空间满了
  • ORA-01654: unable to extend index → 索引无法扩展,通常是索引所在表空间满了
  • 处理前先看报错里的 segment_type 与 tablespace_name,确认是临时还是永久表空间,两者做法不同
扩容的三种手段
-- 1) 给已有数据文件加大
-- 注意:这里必须写控制文件中登记的实际路径,或直接用 file#;
-- 只写裸文件名会报 ORA-01516(指定的文件不存在)
ALTER DATABASE DATAFILE '/u01/oradata/ORCL/app_data01.dbf' RESIZE 500M;
-- 用编号更省事,file# 查 v$datafile
ALTER DATABASE DATAFILE 5 RESIZE 500M;

-- 2) 打开自动扩展
ALTER DATABASE DATAFILE '/u01/oradata/ORCL/app_data01.dbf'
  AUTOEXTEND ON NEXT 100M MAXSIZE 4G;

-- 3) 新增数据文件
ALTER TABLESPACE app_data
  ADD DATAFILE '/u01/oradata/ORCL/app_data02.dbf' SIZE 200M
  AUTOEXTEND ON NEXT 100M MAXSIZE 4G;

查询实际文件路径:SELECT file#, name FROM v$datafile;(或 dba_data_files)。

只作示例阅读:改数据库/实例参数。请在独立学习数据库中练习。

提示 生产环境建议设 AUTOEXTEND ON 但仍留 MAXSIZE 上限,同时配好表空间使用率告警,不要等应用报错才发现。

21.4段、区、块

  • 数据块(Block):I/O 的最小单位,由 DB_BLOCK_SIZE 决定,建库后不可改
  • 区(Extent):连续数据块的集合,是空间分配的单位
  • 段(Segment):一个区以上的集合,对应一个表、索引或分区等对象
  • ASSM(自动段空间管理)用位图跟踪块的使用状态,避免手工调整 FREELIST
  • 高水位线(HWM):段中已使用过的块上限;DELETE 不会降低它,所以删数据不释放空间,需要 SHRINK 或 MOVE
收缩表释放空间
-- 允许行移动,然后收缩
ALTER TABLE employees_demo ENABLE ROW MOVEMENT;
ALTER TABLE employees_demo SHRINK SPACE CASCADE;
-- CASCADE 连带收缩索引

-- 或者更彻底:MOVE 重建
-- 先建个索引,好观察 MOVE 之后索引的状态
CREATE INDEX idx_demo_salary ON employees_demo (salary);

-- 不带 TABLESPACE 就是搬到当前表空间,避免依赖某个特定表空间是否存在
ALTER TABLE employees_demo MOVE;

-- MOVE 会让表上的原有索引全部变为 UNUSABLE,必须重建
-- 索引名请用实际存在的,可先查:
-- SELECT index_name, status FROM user_indexes WHERE table_name = 'EMPLOYEES_DEMO';
ALTER INDEX idx_demo_salary REBUILD;

只作示例阅读:5 行写入限制下只开放单独创建普通空表;CTAS、删表、清空表、改结构、触发器和存储程序不允许执行。请在独立学习数据库中练习。

练习

3 题 · 先自己写,再展开对照

参考答案

风险是数据文件一直长下去,直到把磁盘写满。

磁盘被写满的后果不只是这个表空间写不进去,而是整个实例可能挂起:
后台进程(DBWn/CKPT)无法写盘,严重时数据库进入挂起状态,
影响所有业务,甚至难以连接进去清理。

所以实践上:AUTOEXTEND ON 要配 MAXSIZE 上限,并配合表空间使用率告警;
宁可提前扩容,也不要让它无限增长到把磁盘吃光。

自评要点

  • 指出可能写满磁盘
  • 指出后果不止该表空间,而是整个实例受影响
  • 给出 MAXSIZE 加告警的实践

参考答案

因为 DELETE 只把数据块标记为可复用,不降低高水位线(HWM)。
高水位线以上的空间才算未使用,所以从表空间角度看空间仍被该段占用。

真正释放的两种方式:

1) 收缩(在线,影响小)
ALTER TABLE big_table ENABLE ROW MOVEMENT;
ALTER TABLE big_table SHRINK SPACE CASCADE;
-- CASCADE 连带收缩索引

2) MOVE 重建(会移动数据,需要额外空间,且原索引会变为 UNUSABLE)
ALTER TABLE big_table MOVE TABLESPACE app_data;
ALTER INDEX idx_xxx REBUILD;
-- 必须重建

如果目的是定期清理历史数据,更好的方案是分区表加 DROP PARTITION,
那是 DDL,瞬时完成且自动释放空间。

自评要点

  • 指出 HWM 不下降
  • 给出 SHRINK 或 MOVE + REBUILD
  • 提到分区表 DROP PARTITION 是更优解

参考答案

不一定。

ORA-01652 报的是某个段无法在指定表空间内扩展,segment_type 可能是
temporary、table、table partition、index、LOB 等,
永久表空间不足同样会报这个错。

所以第一件事是看报错信息里的 segment_type 和 tablespace_name,
再决定:
- temporary / 排序类 → 查 DBA_TEMP_FILES,扩大 TEMP
- table → 查该永久表空间的 DBA_DATA_FILES,扩容或清理
- index → 索引所在表空间扩容

对比记忆:
ORA-01653 是 unable to extend table(表扩展不了)
ORA-01654 是 unable to extend index(索引扩展不了)

自评要点

  • 否定必是临时表空间的说法
  • 先看 segment_type 与 tablespace_name
  • 能区分 01652 / 01653 / 01654
← 上一章

用户与权限管理

下一章 →

备份与恢复