dbms_fga.add_policy 通过 audit_column 参数指定敏感字段实现列级监控,仅 select 有效且需全表或唯一索引扫描触发;策略名须唯一,object_schema/object_name 大小写需准确,audit_condition 不可为空。
怎么用 dbms_fga.add_policy 监控某张表的敏感字段
核心是把策略绑定到具体列上,不是整张表。oracle fga 默认只对 select 有效(insert/update/delete 不触发),且必须走全表扫描或索引唯一扫描才可能触发——如果查询走了非唯一索引范围扫描,很可能漏审。
实操建议:
-
object_schema和object_name必须写准确大小写(依赖数据库是否区分大小写),推荐全大写避免歧义 -
audit_condition别空着,哪怕写'1=1';为空时 Oracle 可能跳过策略加载,不报错但也不生效 -
audit_column支持逗号分隔多个列,如'SALARY,SSN',但注意:只要访问其中任一列就触发审计,不是“同时访问才触发” - 策略名
policy_name在同 schema 下必须唯一,重复会报ORA-28100
为什么 DBMS_FGA.ENABLE_POLICY 后还是没日志
FGA 日志默认写进 DBA_FGA_AUDIT_TRAIL 视图,但前提是数据库启用了审计功能且用户有相应权限。常见断点不在策略本身,而在环境配置。
排查要点:
- 确认
AUDIT_TRAIL参数不是NONE(查SHOW PARAMETER audit_trail),FGA 要求至少为DB或OS - 执行策略的用户必须有
EXECUTE权限 onDBMS_FGA,且被审计表要有SELECT权限(否则连查询都失败,更别说审计) - 检查
V$XML_AUDIT_TRAIL或DBA_COMMON_AUDIT_TRAIL(12c+)是否开启统一审计——若开了统一审计,FGA 日志会合并进去,DBA_FGA_AUDIT_TRAIL可能为空 - 测试语句必须真的“触达”被审计列,比如
SELECT name FROM emp不会触发audit_column => 'SALARY'的策略
DBMS_FGA.DROP_POLICY 删除不了策略?常见卡点
删不掉通常不是权限问题,而是策略正被其他会话引用,或者名字拼错了。Oracle 不报“不存在”,而常静默失败或抛 ORA-28113(policy predicate has error),容易误判。
安全操作步骤:
- 先查策略是否存在:
SELECT * FROM DBA_AUDIT_POLICIES WHERE POLICY_NAME = 'MY_SALARY_POLICY' - 确认
object_schema参数和建策略时一致,删策略时也得传进去,不能只靠策略名 - 如果有同名策略在不同 schema,必须指定
object_schema,否则可能删错 - 删除后建议立刻查
DBA_AUDIT_POLICIES确认消失,别只信返回成功
字段级审计的性能代价和绕过风险
FGA 对每个匹配查询都会写一条审计记录、触发一次策略判断,高并发下 I/O 和 CPU 开销明显。更关键的是,它很容易被绕过——不是技术缺陷,而是设计使然。
需要注意:
- 审计只作用于 SQL 引擎层,PL/SQL 块内直接赋值
v_salary := emp_rec.salary不触发 FGA - 物化视图刷新、DBLINK 查询、某些并行查询路径可能跳过策略检查
-
audit_column是“列名字符串匹配”,不校验是否真从该列取值;比如SELECT salary*1.1 FROM emp仍算访问SALARY - 如果业务大量使用绑定变量 + 动态 SQL,且列名拼在字符串里(如
'SELECT ' || col_name || ' FROM ...'),FGA 无法预知列名,策略失效
真正要防数据泄露,得配合视图封装、VPD(虚拟专用数据库)、TDE 加密,FGA 只适合做事后追踪和合规留痕。它不拦访问,只记谁看了什么——这点很多人一开始没想明白。










