PCTUSED在ASSM(AUTO)表空间中完全失效,仅PCTFREE生效;仅在MANUAL段管理下,当块使用率≤PCTUSED时才重新加入freelist供INSERT使用。
pctused 在现代 oracle 中基本不生效,除非你明确禁用了 assm。 如果你的表空间 segment_space_management 是 auto(99% 的新库默认如此),那么 pctused 被完全忽略,只保留 pctfree 用于控制块的更新预留空间。强行设置它不会报错,但也不会起作用。
为什么 ALTER TABLE ... PCTUSED 不生效?
执行 ALTER TABLE t1 STORAGE (PCTUSED 30) 后查 USER_TABLES.PCT_USED 可能显示 30,但这只是元数据记录,Oracle 内核在 ASSM 下根本不读这个值。真正决定块能否被重用的是位图(bitmap)中的状态位,而不是某个百分比阈值。
- 用
SELECT tablespace_name, segment_space_management FROM user_tablespaces确认表空间是否为AUTO - 如果是
AUTO,PCTUSED设置会被静默忽略,DBA_SEGMENTS和块头 dump 都看不到它的影响 - 只有
MANUAL段管理才依赖FREELIST+PCTUSED机制,而这种模式在 12c+ 新建数据库中已被弃用
PCTUSED 在 MANUAL 段管理下的真实行为
当表空间强制设为 MANUAL(如通过 CREATE TABLESPACE ... SEGMENT SPACE MANAGEMENT MANUAL),PCTUSED 才会参与 freelist 管理逻辑:
- 块使用率 ≤
PCTUSED时,被重新加入FREELIST,允许新INSERT - 块使用率 ≥
1 - PCTFREE时,从FREELIST移出,禁止新INSERT(但仍可UPDATE) - 典型陷阱:设
PCTUSED = 70会导致块刚删掉少量行就立刻被放回 freelist,引发频繁的块争用和 ITL 等待 - 实际效果高度依赖并发写入压力 —— 单用户场景下几乎看不出差异
想真正回收空间?别碰 PCTUSED,改用别的手段
依赖 PCTUSED 触发空间重用是低效且不可控的。更可靠的做法是绕过块级阈值逻辑:
- 对大表做
ALTER TABLE t1 SHRINK SPACE COMPACT,直接降低高水位线(HWM),并重排块内行 - 配合启用
ROW MOVEMENT,否则SHRINK会报错ORA-10636 - 用
DBMS_SPACE.SPACE_USAGE查看段的实际未使用块数,比猜PCTUSED值靠谱得多 - 如果碎片严重且无法停机,考虑
CREATE TABLE AS SELECT+EXCHANGE PARTITION替代方案
真正容易被忽略的点是:即使你在 MANUAL 表空间里把 PCTUSED 设成 1,也不代表所有块都会立刻被重用 —— 它只影响后续的 INSERT 路由决策,已存在的空闲块是否在 freelist 上,还取决于当时的 freelist 分配状态和事务一致性快照。











