很多企业的核心业务表里都存放着敏感数据,比如员工薪资、客户手机号、银行卡号等。当这类表被开发人员或者第三方系统随意查询时,DBA往往只能看到有人执行过SELECT语句,却无法知道查的是哪一条数据、是否命中了敏感记录。Oracle提供的FGA(Fine-Grained Auditing,细粒度审计)正是为了解决这个问题,它可以基于行级条件触发审计,只在查询结果满足特定条件时才记录日志,既精准又避免了日志爆炸。

FGA与普通审计的区别
Oracle传统的审计功能(通过AUDIT语句开启)只能做到语句级别或者对象级别。比如对表employees开启审计后,任何人对这张表执行SELECT都会被记录,日志里包含用户名、时间、终端信息等,但无法判断这次查询到底碰没碰到敏感行。假设一张表有百万行数据,某个人只查了一条公开信息,普通审计也会记一笔,长期下来审计表会变得非常庞大,真正有价值的记录反而被淹没。
FGA的核心改进在于引入了审计条件。我们可以在策略里写一个WHERE子句风格的布尔表达式,例如salary > 50000。当用户查询的数据集与该条件有交集时,审计才会触发。换句话说,查普通数据不留痕,查高薪数据才记录,日志量大幅减少,定位问题也更快。此外,FGA还支持记录SQL文本、绑定变量值,甚至通过dbms_fga.execute处理句柄函数实现实时告警,这些能力都是普通审计不具备的。
需要注意一点,FGA在Oracle 9i刚推出时只能审计SELECT语句,从10g开始已经支持INSERT、UPDATE、DELETE等DML操作,覆盖面有了明显提升。对于大多数敏感数据防泄漏场景,SELECT审计依然是最常用的用法。
案例准备:创建测试表与测试用户
下面用一个完整的案例来演示。假设公司有一张员工薪资表,存放员工的姓名、部门和薪资,人事部门要求:任何对薪资高于15000的记录的查询都必须留痕。我们先以sys或system用户登录,创建测试环境和测试用户。
-- 使用DBA账号连接 CONN system/password@orcl -- 创建测试表空间与用户 CREATE TABLESPACE fga_ts DATAFILE 'fga_ts01.dbf' SIZE 50M AUTOEXTEND ON; CREATE USER app_user IDENTIFIED BY App#2024 DEFAULT TABLESPACE fga_ts QUOTA UNLIMITED ON fga_ts; GRANT CONNECT, RESOURCE TO app_user; -- 用应用用户创建业务表 CONN app_user/App#2024@orcl CREATE TABLE emp_salary ( emp_id NUMBER PRIMARY KEY, emp_name VARCHAR2(50), dept_name VARCHAR2(30), salary NUMBER(10,2) ); -- 插入测试数据 INSERT INTO emp_salary VALUES (1, '张伟', '销售部', 8000); INSERT INTO emp_salary VALUES (2, '李娜', '技术部', 26000); INSERT INTO emp_salary VALUES (3, '王强', '财务部', 32000); INSERT INTO emp_salary VALUES (4, '赵敏', '人事部', 9000); COMMIT;
到这里测试环境就搭好了。表里四条数据中有两条薪资超过15000,按照需求,只有查询结果涉及这两条记录时才应该触发审计。接下来创建FGA审计策略。
创建FGA审计策略的核心步骤
创建策略使用dbms_fga.add_policy过程。这个过程有多个参数,其中最关键的四个是:object_schema指定方案名,object_name指定表名,policy_name指定策略名,audit_condition指定审计条件。我们结合上面的需求来写。
-- 以system用户执行
BEGIN
dbms_fga.add_policy(
object_schema => 'APP_USER',
object_name => 'EMP_SALARY',
policy_name => 'AUD_HIGH_SALARY',
audit_condition => 'SALARY > 15000',
audit_column => 'SALARY, EMP_NAME',
handler_schema => NULL,
handler_module => NULL,
enable => TRUE,
statement_types => 'SELECT',
audit_trail => DBMS_FGA.DB + DBMS_FGA.EXTENDED,
audit_column_opts => DBMS_FGA.ANY_COLUMNS
);
END;
/
逐个解释这些参数的含义。audit_condition是触发审计的行级条件,只有查询的数据与满足该条件的行有交集时才记录日志。audit_column限定了关注的列,配合audit_column_opts使用:取值为DBMS_FGA.ANY_COLUMNS表示只要查询涉及其中任意一列就纳入审计;取值为DBMS_FGA.ALL_COLUMNS则要求查询必须同时包含所有指定列。
audit_trail参数决定了记录的详细程度,这是容易被忽略但很关键的一项。默认值DBMS_FGA.DB只记录基本信息到数据库表;加上DBMS_FGA.EXTENDED后会额外记录SQL文本和绑定变量;如果写成DBMS_FGA.XML + DBMS_FGA.EXTENDED,日志会以XML格式写到操作系统文件而不是数据库表里。生产环境中推荐至少加上EXTENDED,否则事后只看到一条记录却不知道执行了什么SQL,排查会很被动。
另外要提醒的是,audit_condition中不能出现函数调用中的某些自定义逻辑,比如SYSDATE可以用,但引用其他自定义PL/SQL函数可能引发性能问题甚至报错,条件里也不要使用OR逻辑,官方文档明确指出OR会导致审计条件被忽略,任何查询都会被记录。
验证审计效果并查询日志
策略创建完成后,用测试用户执行几次不同类型的查询来验证效果。分别查一条低薪记录、一条高薪记录,再执行一次全表查询。
-- 切换到应用用户 CONN app_user/App#2024@orcl -- 查询1:只查低薪记录,理论上不触发审计 SELECT emp_name, salary FROM emp_salary WHERE emp_id = 1; -- 查询2:查高薪记录,触发审计 SELECT emp_name, salary FROM emp_salary WHERE emp_id = 2; -- 查询3:全表查询,结果包含高薪行,触发审计 SELECT * FROM emp_salary;
接下来用DBA身份查询FGA审计日志。日志存放在dba_fga_audit_trail视图中,这是查询审计结果最直接的入口。
CONN system/password@orcl
SELECT session_id,
db_user,
os_user,
object_name,
policy_name,
sql_text,
timestamp
FROM dba_fga_audit_trail
WHERE policy_name = 'AUD_HIGH_SALARY'
ORDER BY timestamp DESC;
执行后会看到查询2和查询3各产生一条记录,而查询1没有任何痕迹,这正是audit_condition起作用的结果。日志中的sql_text列清晰记录了原始SQL语句,lsql_text和lsql_bind在EXTENDED模式下还能记录超长SQL和绑定变量。如果开启了查询结果集记录(9i R2之后FGA会捕获查询返回的满足条件的数据),可以通过dbms_fga相关的转储手段进一步分析。
除了查日志,日常管理还需要几个辅助操作:查看当前所有策略使用dba_audit_policies视图;临时关闭某个策略而不删除它,调用dbms_fga.disable_policy;重新启用调用dbms_fga.enable_policy;彻底删除则调用dbms_fga.drop_policy。
-- 查看策略状态
SELECT policy_name, object_name, enabled FROM dba_audit_policies;
-- 临时禁用策略
BEGIN
dbms_fga.disable_policy(
object_schema => 'APP_USER',
object_name => 'EMP_SALARY',
policy_name => 'AUD_HIGH_SALARY'
);
END;
/
-- 彻底删除策略
BEGIN
dbms_fga.drop_policy(
object_schema => 'APP_USER',
object_name => 'EMP_SALARY',
policy_name => 'AUD_HIGH_SALARY'
);
END;
/
生产环境使用FGA的注意事项
第一是性能问题。FGA的实现原理是优化器在解析查询时自动将审计条件并入执行计划做判断,这意味着每条命中策略表的查询都会多一次条件评估。对于查询频繁的热点表,尤其是没有合适索引的场景,条件列上务必建立索引,否则可能引发全表扫描级别的额外开销。建议先在测试环境通过执行计划对比评估影响。
第二是日志空间管理。FGA日志默认写入SYSTEM表空间的SYS.FGA_LOG$基表,如果不加清理,时间一长会挤占系统空间。可以定期通过dbms_audit_mgmt包清理过期审计记录,或者将audit_trail改为XML模式让日志落盘到独立目录。清理前记得按合规要求做好归档,很多行业对审计日志的保留年限有硬性规定。
第三是权限控制。策略的创建和删除需要适当权限,普通用户不应拥有执行dbms_fga包的权利,否则审计机制本身可能被绕过或篡改。建议将策略管理集中在DBA层面,同时把dba_fga_audit_trail的查询权限只授予审计岗位人员,形成管理闭环。
掌握这套流程后,无论是等保测评要求的敏感数据访问留痕,还是日常排查数据泄露源头,FGA都能提供一个开销可控、定位精准的解决方案。建议在正式上线前,先对目标表的典型查询做一轮压测,确认审计条件与索引设计匹配后再全量推开。
Oracle FGA细粒度审计DBMS_FGA修改时间:2026-09-05 17:15:08