oracle fga审计日志默认写入sys.fga_log$表,若未指定表空间则位于system表空间;查询dba_segments可确认其物理位置,若tablespace_name='system'即为根因,需及时迁移至sysaux等独立表空间并清理。
查 aud$ 或 fga_log$ 是否在 system 表空间
开启 fine-grained auditing(fga)后,审计日志默认写入 fga_log$ 表;若未显式指定表空间,该表会建在 system 表空间。一旦业务高频触发 fga 策略(比如对敏感字段的 select),fga_log$ 会迅速膨胀,直接拖垮 system。
执行以下语句确认位置:
SELECT owner, segment_name, tablespace_name
FROM dba_segments
WHERE segment_name IN ('AUD$', 'FGA_LOG$')
AND owner = 'SYS';
如果 tablespace_name 是 'SYSTEM',这就是根因。别只看参数 audit_trail 是否为 DB——FGA 日志不走该参数控制,它独立依赖表物理位置。
用 DBA_FGA_AUDIT_TRAIL 快速验证 FGA 是否真在打日志
DBA_FGA_AUDIT_TRAIL 是视图,背后就是 FGA_LOG$。但注意:该视图默认不暴露所有列,且查询可能慢(尤其数据多时)。更稳妥的是直接查基表统计:
- 先看最近 1 小时新增记录数:
SELECT COUNT(*) FROM sys.fga_log$ WHERE ntimestamp# > SYSDATE - 1/24; - 再查高频触发的策略:
SELECT policy_name, object_schema, object_name FROM dba_audit_policies WHERE enabled = 'YES'; - 结合应用日志或 SQL ID,确认哪些业务 SQL 实际命中了这些策略(可用
v$sql+sql_text模糊匹配)
常见误配:对整张大表启用 FGA,且未加 statement_types 限制(如只该抓 UPDATE 却放行所有 DML),或条件谓词太宽泛(如 dept_id > 0),导致每行访问都记一条。
临时止血:清空 FGA_LOG$ 并迁移表空间
别用 DELETE FROM sys.fga_log$ —— 它会生成大量 undo、锁表、且不释放空间。正确做法是:
- 清空:
TRUNCATE TABLE sys.fga_log$;(需SYSDBA权限) - 迁移表空间(避免下次重建又掉坑里):
ALTER TABLE sys.fga_log$ MOVE TABLESPACE sysaux; - 重建索引(迁移后必须做):
ALTER INDEX sys.i_fga_log$_1 REBUILD TABLESPACE sysaux;
注意:MOVE 操作期间 FGA_LOG$ 不可写,建议在低峰期操作;迁移目标表空间(如 SYSAUX)需有足够空闲空间且已关闭自动扩展失控风险。
长期规避:关掉冗余 FGA 策略或改用外部审计
FGA 不是“开了就安全”,而是“开了就得管”。很多系统开着却从不查 DBA_FGA_AUDIT_TRAIL,纯属占空间。排查后发现以下情况应立即调整:
- 策略名含
TEST、DEMO或创建时间早于半年且无任何审计记录 - 同一对象上叠加多个策略,且条件重叠(如对
salary字段既设了范围过滤又设了函数表达式) - 审计目的仅为合规留痕,而非实时风控——此时更适合用 OS 层审计或 Oracle Unified Audit(12c+),后者日志默认存
AUDSYS表空间,隔离性更好
真正难缠的不是空间本身,是没人知道哪些 FGA 策略还在默默吃磁盘。定期跑一遍 SELECT * FROM dba_audit_policies WHERE enabled = 'YES' AND last_modified ,比扩容数据文件有用得多。











