Oracle 11.2.0.4 引入 deferred_segment_creation 參數(預設 TRUE),改變空表/分區的空間分配行為:無數據時不分配 Segment/Extent。此特性節省空間但導致傳統 EXP 導出時跳過無 Segment 的對象,造成導出不完整。本文詳解機制、影響範圍與三種解決方案。
SYS@ORCL> SHOW PARAMETER segment
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
deferred_segment_creation boolean TRUE
| 場景 | deferred_segment_creation = TRUE | deferred_segment_creation = FALSE |
|---|---|---|
| SYS/SYSTEM 用戶建空表 | 立即分配 Segment(不遞延) | 立即分配 |
| 普通用戶建空表 | 不分配 Segment/Extent | 立即分配 |
| 空表首次 INSERT | 自動分配 Segment | 已存在 |
| TRUNCATE TABLE | 保留 Segment(不釋放) | 保留 |
| TRUNCATE TABLE DROP ALL STORAGE | 釋放 Segment | 釋放 |
-- 方法 1:查看 DBA_SEGMENTS(無行 = 未分配)
SELECT owner, segment_name, segment_type, tablespace_name, bytes
FROM dba_segments
WHERE segment_name = 'T1';
-- 方法 2:DBMS_METADATA 顯示 DDL(含 SEGMENT CREATION 子句)
SET LONG 99999
SELECT dbms_metadata.get_ddl('TABLE', 'T1') FROM dual;
-- 輸出包含 "SEGMENT CREATION DEFERRED" 或 "SEGMENT CREATION IMMEDIATE"
傳統 EXP 依賴 DBA_SEGMENTS 判斷對象是否存在,無 Segment 的表/索引/分區被視為不存在而跳過。Data Pump (EXPDP) 不受影響,因其讀取字典元數據而非段視圖。
ALTER SYSTEM SET deferred_segment_creation = FALSE SCOPE = BOTH;
-- 或 PFILE/SPFILE 修改後重啟
⚠️ 已建空表不會自動分配 Segment,需配合方案 2/3 處理存量。
CREATE TABLE t1 (id NUMBER) SEGMENT CREATION IMMEDIATE;
-- 覆蓋參數預設行為,強制分配初始 Extent
-- 方法 A:分配一個 Extent(推薦,無需數據)
ALTER TABLE t1 ALLOCATE EXTENT;
-- 方法 B:插入一行再刪除(產生 Undo/Redo)
INSERT INTO t1 VALUES (1);
COMMIT;
DELETE FROM t1 WHERE id = 1;
COMMIT;
-- 批次處理腳本
BEGIN
FOR obj IN (SELECT owner, segment_name FROM dba_tables
WHERE owner NOT IN ('SYS','SYSTEM')
AND NOT EXISTS (SELECT 1 FROM dba_segments s
WHERE s.owner = dba_tables.owner
AND s.segment_name = dba_tables.table_name))
LOOP
EXECUTE IMMEDIATE 'ALTER TABLE ' || obj.owner || '.' || obj.segment_name || ' ALLOCATE EXTENT';
END LOOP;
END;
/
ALLOCATE EXTENT。ALTER TABLE ... MODIFY PARTITION p1 ALLOCATE EXTENT。DBA_TABLES vs DBA_SEGMENTS 差集,自動分配或報警。