Oracle 19c中无法实现真正的“全库细粒度审计”,因FGA本质是对象级,必须指定OBJECT_SCHEMA和OBJECT_NAME;所谓“全库”只能通过批量建策或结合统一审计模拟,二者机制不同、用途互补。
oracle 19c 中无法直接通过统一审计(unified auditing)实现“数据库级别”的细粒度审计——细粒度审计(fga)天生是对象级的,必须指定 object_schema 和 object_name;所谓“全库 fga”只能靠批量建策或结合统一审计策略模拟,但底层机制完全不同。
为什么 DBA 常误以为能开“全库 FGA”
细粒度审计本质是基于谓词匹配的行级/列级拦截,依赖 Oracle 内核对 SQL 执行计划中访问路径的重写(如插入隐式 WHERE 条件)。它不作用于语句类型(如所有 SELECT),也不覆盖系统对象或数据字典表。常见误解来源:
- 把
DBMS_FGA.ADD_POLICY的STATEMENT_TYPES => 'SELECT'当成“审计所有 SELECT”,实际只对显式指定了该策略的表生效 - 试图对
OBJECT_NAME => '%'或留空建策,会报ORA-47000: invalid object name - 混淆统一审计策略(
CREATE AUDIT POLICY ... ACTIONS SELECT ANY TABLE)和 FGA:前者记录“谁查了什么表”,后者记录“谁查了表里哪些行/列”
真正可行的“类全库”细粒度监控方案
没有银弹,但有可落地的组合路径。核心思路:用统一审计兜底行为类型,用 FGA 精准捕获高敏对象——二者并存不冲突(19c 支持混合审计源):
- 对敏感 Schema(如
HR、FINANCE)下的关键表,逐个调用DBMS_FGA.ADD_POLICY,明确指定AUDIT_COLUMN和AUDIT_CONDITION(例如salary > 10000) - 同时启用统一审计策略捕获跨 Schema 行为:
CREATE AUDIT POLICY global_ddl ACTIONS CREATE ANY TABLE, DROP ANY TABLE,再AUDIT POLICY global_ddl - 若需覆盖大量表,可用脚本生成批量建策语句:
SELECT 'BEGIN DBMS_FGA.ADD_POLICY(OBJECT_SCHEMA=>'''||owner||''', OBJECT_NAME=>'''||table_name||''', POLICY_NAME=>'''||owner||'_'||table_name||'_fga'', STATEMENT_TYPES=>''SELECT''); END;' FROM dba_tables WHERE owner IN ('HR','FINANCE') AND table_name NOT LIKE 'BIN$%';
DBMS_FGA.ADD_POLICY 必须填的参数与典型坑
漏掉任一必填项会导致策略创建成功但完全不触发审计。注意以下硬性要求:
-
OBJECT_SCHEMA和OBJECT_NAME不可为空,且对象必须存在(不能是同义词或不存在的表名) -
POLICY_NAME在同一 Schema 下必须唯一;重复创建会报ORA-47002: policy already exists,需先DBMS_FGA.DROP_POLICY -
ENABLE => TRUE是默认值,但显式写出更安全;设为FALSE后必须手动DBMS_FGA.ENABLE_POLICY -
AUDIT_CONDITION中不能用绑定变量,只能是纯 SQL 表达式(如'dept_id = 10'),且字段必须存在于目标表中 - 策略启用后,首次命中条件的查询会明显变慢(因需解析谓词+写日志),后续缓存会缓解
查不到审计记录?优先检查这三处
FGA 日志写入 DBA_FGA_AUDIT_TRAIL,但该视图默认不暴露真实执行 SQL(SQL_TEXT 为空),且受权限限制:
- 确认用户有
SELECT_CATALOG_ROLE或直接授予SELECT ON DBA_FGA_AUDIT_TRAIL(仅 SYS 或有授权者可查) - 执行审计操作的用户必须对目标表有对应 DML 权限;如果只授了
SELECT ANY TABLE,但没在具体表上授权,FGA 不触发 -
DBA_FGA_AUDIT_TRAIL中的SQL_BIND字段只记录绑定变量值,不记录完整语句——真要查原始 SQL,得开统一审计的ACTIONS SELECT策略并查UNIFIED_AUDIT_TRAIL.SQL_TEXT
细粒度审计不是开关,而是手术刀;它的价值不在“覆盖广”,而在“打点准”。别试图用它替代统一审计的全局行为记录,也别指望靠一个策略管住整个数据库——设计时先圈出真正需要监控的 5 张表、3 个列、2 类条件,比盲目铺开更重要。


















