Oracle 的SHRINK 操作实现原理
Oracle 的SHRINK 操作实现原理
Oracle 的 SHRINK
操作是一种在线重组表空间的技术,它可以在不重建表的情况下减少高水位线(HWM)并回收空闲空间。
基本实现原理
-
核心目标:
- 降低高水位线(HWM)
- 回收未使用的空间
- 消除行迁移和行链接
- 在线操作(允许DML并发)
-
与MOVE的关键区别:
- SHRINK是渐进式重组,MOVE是原子性重建
- SHRINK保持ROWID不变,MOVE会改变ROWID
- SHRINK不需要重建索引,MOVE需要
详细工作流程
1. 准备阶段
-- 必须启用行移动功能
ALTER TABLE table_name ENABLE ROW MOVEMENT;
2. 收缩执行阶段
ALTER TABLE table_name SHRINK SPACE [COMPACT] [CASCADE];
两阶段操作机制:
-
压缩阶段(COMPACT):
- 重新组织数据行,填充空闲空间
- 不立即释放空间给表空间
- 可中断后继续执行
-
空间释放阶段:
- 调整高水位线
- 将空闲空间归还表空间
- 需要额外的系统资源
3. 内部操作伪代码
def shrink_table():# 第一阶段:压缩for each block in table_blocks:if block has free_space:move_rows_from_higher_blocks()compact_rows()# 第二阶段:调整HWMnew_hwm = last_used_block + 1update_segment_header(new_hwm)release_free_blocks()
关键技术点
1. 行移动机制
- 使用临时空间记录行移动映射
- 保持索引结构不变(不改变ROWID)
- 通过内部事务保证一致性
2. 空间管理
- 使用位图跟踪空闲空间
- 优先填充前半部分数据块
- 逐步释放末尾的空闲块
3. 并发控制
- 使用行级锁而非表锁
- 允许DML操作并发执行
- 可能短暂阻塞DDL操作
存储变化示意图
收缩前:
[已用块][空闲块][已用块][空闲块][HWM]
收缩后:
[紧凑的已用块][HWM] | 释放的空间
参数与限制
1. 关键参数影响
COMPACT
:只压缩不释放空间CASCADE
:级联收缩相关对象(如索引)SHRINK SPACE
:完整执行两阶段
2. 主要限制
- 必须启用
ROW MOVEMENT
- 不支持含LOB列的表(除非使用特殊选项)
- 不能用于系统表空间中的对象
- 集群表、IOT等特殊表有限制
性能优化建议
-
分批处理大表:
-- 先压缩多次再最终释放 ALTER TABLE large_table SHRINK SPACE COMPACT; ALTER TABLE large_table SHRINK SPACE COMPACT; ALTER TABLE large_table SHRINK SPACE;
-
最佳执行时机:
- 低业务负载时段
- 表有大量删除/更新操作后
- 定期维护窗口期
-
监控方法:
-- 查看收缩进度 SELECT sql_text, sofar, totalwork FROM v$session_longops WHERE opname LIKE '%SHRINK%';-- 评估收缩效果 SELECT table_name, blocks, empty_blocks FROM user_tables WHERE table_name = 'YOUR_TABLE';
内部实现细节
-
UNDO生成:
- 只为行移动生成UNDO
- 比MOVE操作生成的UNDO少得多
-
REDO生成:
- 记录行移动和HWM变更
- 量级取决于移动的行数
-
临时空间使用:
- 需要少量临时空间
- 主要用于跟踪行移动
与MOVE操作的对比
特性 | SHRINK | MOVE |
---|---|---|
锁定级别 | 行级锁 | 排他锁 |
ROWID变化 | 保持不变 | 全部改变 |
索引状态 | 保持有效 | 需要重建 |
空间释放 | 渐进式释放 | 完全重组 |
高水位线处理 | 可能降低但不完全重置 | 完全重置 |
适用场景 | 日常维护 | 大规模重组 |
实际案例
-- 1. 准备表
CREATE TABLE sales_data AS SELECT * FROM sales_history;
DELETE FROM sales_data WHERE sale_date < ADD_MONTHS(SYSDATE, -24);-- 2. 检查空间使用
SELECT segment_name, blocks, bytes/1024/1024 MB
FROM user_segments
WHERE segment_name = 'SALES_DATA';-- 3. 执行收缩
ALTER TABLE sales_data ENABLE ROW MOVEMENT;
ALTER TABLE sales_data SHRINK SPACE CASCADE;-- 4. 验证结果
SELECT blocks, empty_blocks
FROM user_tables
WHERE table_name = 'SALES_DATA';
SHRINK操作是Oracle提供的一种高效在线空间重组工具,特别适合需要最小化停机时间的生产环境维护。理解其实现原理有助于DBA更有效地使用这一功能。