ALTER TABLE ... MOVE TABLESPACE 可迁移表,但需重建索引、显式处理LOB、避开业务高峰;因ROWID变更致索引失效,LOB不指定则滞留原表空间,大表需双倍空间且ONLINE限制多。
直接结论:用 alter table ... move tablespace 可以迁移表,但必须配套重建索引,lob 字段要单独处理,大表务必避开业务高峰。
为什么 MOVE TABLESPACE 后查询变慢甚至报错
执行 ALTER TABLE t1 MOVE TABLESPACE users 后,表数据被物理复制到新位置,所有行的 ROWID 全部改变。而索引是靠 ROWID 定位数据的,所以原索引自动变成 UNUSABLE 状态——这时走索引的查询会失败或退化为全表扫描。
- 查状态:
SELECT index_name, status FROM user_indexes WHERE table_name = 'T1';会看到UNUSABLE - 不重建就 DML(如
INSERT/UPDATE)可能报ORA-01502: index ... or partition of such index is in unusable state - 即使只读查询,优化器也可能因索引失效而选错执行计划
MOVE 对 LOB 字段必须显式声明
如果表含 CLOB、BLOB 列,只写 MOVE TABLESPACE 不会迁移 LOB 段——它仍留在原表空间,且可能引发后续 INSERT 失败(如 ORA-22993: specified amount is greater than actual source length 或空间配额不足)。
- 正确写法:
ALTER TABLE t1 MOVE TABLESPACE users LOB (clob_col) STORE AS (TABLESPACE users); - 多列 LOB:
LOB (c1, c2, c3),不能漏写 - 若未指定
STORE AS,LOB 默认用原表空间,MOVE 后可能跨表空间引用,违反一致性约束
分区表和 Online Move 的关键限制
普通 MOVE 是 DDL 锁表操作(X 锁),整个过程 DML 阻塞。Oracle 12.2+ 支持 ONLINE,但限制极多:
- 仅限非分区表:
ALTER TABLE t1 MOVE TABLESPACE users ONLINE;—— 自动重建索引,不锁 DML - 分区表只能对单个
PARTITION或SUBPARTITION做ONLINE:ALTER TABLE t1 MOVE PARTITION p1 TABLESPACE users ONLINE UPDATE INDEXES; -
ONLINE不能和LOB子句共存;不能和压缩、存储参数等其他子句混用 - 目标表空间必须启用自动段空间管理(ASSM),否则报
ORA-01747
容易被忽略的权限与空间陷阱
看似一条 SQL 就能跑通,实际卡在权限或空间上最常见:
- 用户必须对目标表空间有配额:
ALTER USER scott QUOTA UNLIMITED ON users;,否则报ORA-01950: no privileges on tablespace 'USERS' -
MOVE过程中需要「双倍」临时空间:原表大小 + 新表大小(同时存在),小表影响不大,100GB 表得确保目标表空间有额外 100GB 空闲 - 系统表空间(
SYSTEM、SYSAUX)禁止用户执行MOVE,连SELECT权限都不该开放 - 表上有
ENABLE ROW MOVEMENT不是MOVE的前提(那是SHRINK要求的),别混淆
真正麻烦的不是语法写错,而是忘了索引失效、LOB 落单、空间不够这三件事——它们往往在上线后几小时才暴露,且排查路径曲折。动手前先 SELECT 查一遍 USER_INDEXES 和 USER_LOBS,比重跑十遍脚本省事得多。


















