alter user default tablespace 仅影响新建对象,对已有对象无效;迁移需用 alter table move 并处理大小写表名、lob字段、分区表三类细节,move 后索引变 unusable 必须重建,且操作不可回滚、全程锁表,需手动更新统计信息。

直接执行 ALTER USER DEFAULT TABLESPACE 不起作用
这是最常被误用的操作。设置 ALTER USER DEFAULT TABLESPACE NEW_TBS 只影响后续新建的表、索引等对象,对已有对象完全无效。已有表仍留在原表空间,查询 user_tables 或 dba_segments 会清楚显示 tablespace_name 未变。强行忽略这点,后续查数据或建索引时容易触发 ORA-01502 或空间不足报错。
生成批量 ALTER TABLE MOVE 语句要处理三类细节
不能只拼 ALTER TABLE table_name MOVE TABLESPACE NEW_TBS; 就完事,必须覆盖真实环境中的常见变体:
- 表名含大小写或特殊字符(如
"MyTable"):需加双引号,可用SELECT '"' || table_name || '"' FROM user_tables生成带引号版本 - 含 LOB 字段的表:
MOVE TABLESPACE只迁移表段,LOB 段仍卡在原表空间;必须额外生成ALTER TABLE ... MOVE LOB(column_name) STORE AS (TABLESPACE NEW_TBS)语句 - 分区表:直接
ALTER TABLE ... MOVE会报ORA-14511;必须按分区生成,例如ALTER TABLE t MOVE PARTITION p1 TABLESPACE NEW_TBS
MOVE 后所有普通索引自动变为 UNUSABLE
这是硬性行为,不是 bug。执行完表迁移后,查 user_indexes 会发现 status = 'UNUSABLE'。不重建就查数据,轻则全表扫描,重则直接报 ORA-01502。重建不能只靠 ALTER INDEX ... REBUILD 简单覆盖:
- 优先用
WHERE status = 'UNUSABLE'筛选,避免重建已正常的索引 - 若索引属于刚迁入新表空间的表,建议用
JOIN user_tables关联过滤,防止遗漏分区索引或函数索引 - 生产环境建议加
ONLINE和NOLOGGING(如允许),减少锁和归档压力:ALTER INDEX idx REBUILD TABLESPACE NEW_TBS ONLINE NOLOGGING
整个过程没有事务保护,且全程锁表
ALTER TABLE MOVE 是 DDL 操作,不可回滚,且会持有 EXCLUSIVE 表级锁,期间该表无法写入、甚至部分查询也会阻塞。这不是“慢”,而是“停服级影响”:
- 不要在业务高峰执行;提前评估单表 MOVE 耗时(大表可能数小时)
- LOB 和分区表迁移更耗资源,建议单独拆出、分批执行
- MOVE 完成后统计信息不会自动更新,必须手动跑
DBMS_STATS.GATHER_TABLE_STATS,否则执行计划可能劣化
真正麻烦的从来不是拼 SQL,而是确认每张表的结构特征、预估锁表时间、以及重建索引时是否漏掉某类特殊索引——这些细节一旦跳过,上线后的问题比迁移前还难排查。











