直接用TTS传输历史分区失败,因EXCHANGE PARTITION不支持跨表空间交换,且TTS要求源表空间自包含、只读、无隐式依赖(如物化视图日志、外键、全局索引等),未清理这些依赖会导致ORA-39123或ORA-19721错误。
为什么直接用 TTS 传输历史分区会失败
因为 alter table ... exchange partition 不支持跨表空间交换分区,而 tts(transportable tablespace)要求源分区所在表空间必须是自包含的、只读的,且不能依赖其他表空间的对象(比如全局索引、外键、物化视图日志)。很多人一上来就 alter tablespace ... read only 然后 expdp,结果报 ora-39123: data pump transportable tablespace job failed 或 ora-19721,根本原因是分区仍处于可写状态,或存在隐式依赖。
- 必须先禁用所有影响分区一致性的对象:
DROP MATERIALIZED VIEW LOG ON table_name、DISABLE CONSTRAINT外键、UNUSABLE全局索引 - 确认分区不包含 LOB 段在其他表空间(
SELECT tablespace_name FROM dba_lobs WHERE table_name = 'T' AND column_name = 'C') -
DBMS_TTS.TRANSPORT_SET_CHECK必须返回空结果,否则说明有跨表空间依赖
如何让历史分区真正“可拔插”
不是把整个分区表导出,而是把分区数据“物理挪走”——核心是把分区变成独立表,再用 TTS 导出它所在的表空间。关键步骤是 EXCHANGE PARTITION + CREATE TABLE ... FOR EXCHANGE WITH TABLE,但必须严格匹配结构:
- 目标表必须和分区完全同构:列顺序、类型、NULL 属性、压缩属性、段压缩(
COMPRESS FOR QUERY HIGH也要一致) - 不能有主键/唯一约束(否则
EXCHANGE报ORA-14098),可临时DISABLE VALIDATE - 如果原分区有本地索引,目标表必须建相同 DDL 的本地索引(包括
UNUSABLE状态),否则交换失败 - 交换后立即
ALTER TABLESPACE ... READ ONLY,再EXPDP TRANSPORT_TABLESPACES=ts_name
EXPDP 运行时卡住或报 ORA-39126 的真实原因
不是性能问题,而是元数据导出阶段校验失败。EXPDP 在生成 transportable metadata 时,会扫描所有依赖对象,哪怕你只导一个表空间,只要该表空间里某个表被另一个表空间的物化视图引用,就会中断。
- 查依赖最准的方式:
SELECT * FROM dba_dependencies WHERE referenced_owner = 'SCHEMA' AND referenced_name IN (SELECT segment_name FROM dba_segments WHERE tablespace_name = 'HIST_TS') - 常见漏掉的点:审计策略(
audit_policy)、FGAC 策略(dbms_rls)、统计信息锁(DBMS_STATS.LOCK_TABLE_STATS)都会阻塞 TTS - 导出命令必须加
VERSION=19.0.0(与目标库一致),否则IMPDP会拒绝导入 12c+ 的新特性元数据
目标库导入后查询变慢,不是执行计划问题
是因为分区交换回来后,本地索引默认是 UNUSABLE,而优化器看到索引不可用,可能放弃走索引路径,甚至改用全表扫描——即使你没动 SQL,执行计划也变了。
- 导入后立刻检查:
SELECT index_name, status FROM dba_indexes WHERE table_name = 'T' AND partitioned = 'YES' - 重建本地索引不能用
ALTER INDEX ... REBUILD(只重建当前分区),必须用ALTER INDEX ... REBUILD PARTITION p2022 - 如果用了
INVISIBLE索引,导入后仍是 invisible,需显式ALTER INDEX ... VISIBLE - 统计信息不会自动导入,必须手工
DBMS_STATS.IMPORT_TABLE_STATS或DBMS_STATS.GATHER_TABLE_STATS
真正麻烦的是跨平台 TTS(比如从 Linux x86_64 传到 AIX),字节序和块大小不一致时,CONVERT DATAFILE 这步容易忽略 endianness 校验,导致数据文件头损坏——这种错误往往要等到 IMPDP 后第一次 SELECT 才暴露。

















