flashback data archive表空间满的根源是隐藏历史表(sys_fba_hist_xxxxxx)占用主表所在表空间且不走assm清理;需用alter flashback archive...modify tablespace迁移至本地管理自动段空间表空间,并手动清理孤儿历史表。
flashback data archive 表空间满了怎么办
直接说结论:dba_flashback_archive_tablespaces 视图里显示的表空间用满,不是因为归档数据本身占满,而是因为底层 fbda 为每个启用 fba 的表自动创建的隐藏历史表(如 sys_fba_hist_xxxxxx)所在表空间撑爆了——它默认复用主表所在表空间,且不走自动段空间管理(assm)的常规清理逻辑。
常见错误现象:ORA-55617: Flashback Archive tablespace is full,但查 DBA_TABLESPACES 发现空闲率还有 30%;或者执行 ALTER FLASHBACK ARCHIVE ... PURGE BEFORE SCN 后空间完全不释放。
- 必须确认归档实际存放位置:
SELECT flashback_archive_name, tablespace_name FROM dba_flashback_archive_ts;—— 别只看主表在哪个表空间 - 如果
tablespace_name是SYSTEM或用户默认表空间,立刻迁走:用ALTER FLASHBACK ARCHIVE fba_name MODIFY TABLESPACE new_ts; - 迁移前确保目标表空间是
EXTENT MANAGEMENT LOCAL且SEGMENT SPACE MANAGEMENT AUTO,否则后续 purge 会失败
Flashback Data Archive 的 PURGE 操作为什么没效果
PURGE 不是删数据,而是标记可回收 + 触发后台清理任务;它依赖 _fbda_purge_job_interval 隐含参数(默认 60 分钟),且只清理已过期、且对应历史表上无活跃事务/查询的块。
使用场景:手动清理旧归档后想立刻释放空间,或发现 DBA_SEGMENTS 中 SYS_FBA_HIST_* 段大小没变。
- 先查是否真过期:
SELECT * FROM dba_flashback_archive_tables WHERE flashback_archive_name = 'FBA_NAME';看FLASHBACK_ARCHIVE_NAME和ARCHIVE_TABLE_NAME对应关系 - 强制触发清理:
EXEC DBMS_FLASHBACK_ARCHIVE.PURGE_FLASHBACK_ARCHIVE('FBA_NAME');—— 注意这不是 SQL 命令,得在 PL/SQL 块里跑 - 检查清理进度:
SELECT * FROM v$flashback_archive_cursor;如果CURSOR_STATE是INACTIVE且LAST_PURGE_TIME老旧,说明后台 job 卡住,需查DBA_SCHEDULER_JOB_LOG中FBDA_PURGE_JOB状态
多个 Flashback Archive 共享表空间时的空间争抢问题
Oracle 不限制单个表空间被多少 FBA 共用,但所有 FBA 的历史表都混在同一个段里,ALTER FLASHBACK ARCHIVE ... MODIFY RETENTION 会批量重写元数据,可能引发高并发 DML 下的锁等待和空间碎片。
性能影响:当多个业务系统共用一个 FBA 表空间,且各自 retention 设置差异大(比如 A 设 1 年、B 设 1 天),purge 作业会反复扫描全量历史段,I/O 毛刺明显。
- 按业务生命周期隔离:用
CREATE FLASHBACK ARCHIVE fba_app1 TABLESPACE ts_app1 RETENTION 1 YEAR;单独配表空间 - 避免混用
DEFAULT归档:不要让不同重要级的表都绑定到DEFAULTFBA,它的 retention 修改会影响所有未显式指定 FBA 的表 - 监控真实压力点:
SELECT flashback_archive_name, COUNT(*) cnt FROM dba_flashback_archive_tables GROUP BY flashback_archive_name;超过 50 张表建议拆分
Flashback Data Archive 关闭后空间为什么不释放
禁用 FBA(ALTER TABLE t NO FLASHBACK ARCHIVE)只是切断新 DML 写入历史,已生成的 SYS_FBA_HIST_* 表不会自动删,也不会自动加入 purge 范围——它成了“孤儿段”,DBA 得手动处理。
容易踩的坑:以为关掉就万事大吉,结果半年后发现那个表空间一直没腾出空间,查 DBA_TABLES 又看不到这些历史表名(因为是 SYS 用户下、且 HIDDEN_COLUMN 属性为 YES)。
- 定位孤儿表:
SELECT table_name FROM dba_tables WHERE owner = 'SYS' AND table_name LIKE 'SYS_FBA_HIST_%' AND table_name NOT IN (SELECT archive_table_name FROM dba_flashback_archive_tables); - 安全删除步骤:先
ALTER TABLE SYS.SYS_FBA_HIST_xxxx RENAME TO SYS.SYS_FBA_HIST_xxxx_DEL;,再DROP TABLE SYS.SYS_FBA_HIST_xxxx_DEL; - 注意权限:必须用
SYS AS SYSDBA执行,普通DBA角色无法访问这些对象
最麻烦的地方在于:这些历史表的段头块可能还被 undo 或 buffer cache 引用,DROP 前最好等 1–2 小时冷处理,否则报 ORA-00604 或卡在 drop pending 状态。










