我在之前的一篇文档
利用FGA实现Oracle表的审计中提到Oracle还提供了另一种对表进行审计的方式,以下简单介绍如何启用这种审计线索。再次说明一下,这是一种较老模式的审计方法,有一些缺点,比如设置繁琐,审计信息较难处理,而且使用了trigger可能会有未知的影响。
Oracle对几乎所有表提供了历史记录查看的功能,可以查看当前记录的创建时间,创建人,以及最后更新时间和更新人。
然而在更改的过程却没有被记录下来。有时候需要了解一条记录的整个周期的变化过程,在哪些时间点由什么人更改了哪些字段值,这就需要使用Oracle提供的审计线索功能作为辅助手段完成开发。
审计线索的基本原理是为需要监控的表建立一张对应的Shadow表,并建立一系列相关的Trigger,通过Trigger,每次监控表有更新,就把更新前字段的值以及更新时间,更新人等审计信息记录在shadow表中,从而实现了对表字段级的监控。
本文将介绍审计线索的启用过程,实际实施中碰到的一些限制问题以及解决方法。
审计线索为待审计表建立的审计历史记录表,命名一般为待审计表名称后加“_A”,比如GL_JE_HEADERS的审计线索表就是GL_JE_HEADERS_A。这张审计表就是我们所称的shadow表。
该表有一些特有的状态字段,比如audit_timestamp,audit_user_name,audit_transaction_type分别记录了更新时间,更新人,以及更新的种类,是create还是update 或者是delete。
此外shadow表具有待审计表的一切待审计字段,特别说明的一点是,这些字段的顺序是不以设置顺序决定的。即在设置的时候把字段b放在字段a之前,oracle在建立shadow表的时候,也还是会把a字段放在b字段之前。之所以强调顺序问题的原因在之后有说明。
我们以广发行用户需要监控日记账的产生,修正,审批等过程作为业务背景,详细介绍启用审计线索的步骤。
1.
设置启用审计线索
a.
系统管理员>安全性>审计线索>安装
a)
查询 Oracle用户名
为 ”GL”
的记录。
b)
勾选 “启用跟踪”
c)
保存
b.
系统管理员>安全性>审计线索>组
a)
输入应用产品名:Oracle General
Ledger
b)
输入跟踪组名称:GL_AUDIT_GROUP
c)
在行中创建3个新行,各行的用户表名分别为:
GL_JE_BATCHES
GL_JE_HEADERS
GL_JE_LINES
d)
保存
c.
系统管理员>安全性>审计线索>表
a)
设置GL_JE_BATCHES的审计列;
i.
查找用户表名 GL_JE_BATCHES
ii.
新建并保存如下行
列名
列类型
主关键字
JE_BATCH_ID
数值
Y
BUDGETARY_CONTROL_STATUS
Varchar2
APPROVAL_STATUS_CODE
Varchar2
b)
设置GL_JE_HEADERS的审计列
i.
查找用户表名 GL_JE_HEADERS
ii.
新建并保存如下行
列名
列类型
主关键字
JE_HEADER_ID
数值
Y
CONTROL_TOTAL
数值
DESCRIPTION
Varchar2
ACCRUAL_REV_EFFECTIVE_DATE
日期
JE_BATCH_ID
数值
Y
DEFAULT_EFFECTIVE_DATE
日期
STATUS
Varchar2
CURRENCY_CODE
Varchar2
NAME
Varchar2
Y
PERIOD_NAME
Varchar2
JE_CATEGORY
Varchar2
EXTERNAL_REFERENCE
Varchar2
CURRENCY_CONVERSION_DATE
日期
CURRENCY_CONVERSION_TYPE
Varchar2
CURRENCY_CONVERSION_RATE
数值
REFERENCE_DATE
日期
c)
设置GL_JE_LINES的审计列
i.
查找用户表名 GL_JE_LINES
ii.
新建并保存如下行
列名
列类型
主关键字
DESCRIPTION
Varchar2
ACCOUNTED_CR
数值
ACCOUNTED_DR
数值
ENTERED_CR
数值
ENTERED_DR
数值
CODE_COMBINATION_ID
数值
JE_LINE_NUM
数值
Y
JE_HEADER_ID
数值
Y
d.
在系统管理员职责下运行请求 “审计线索更新表”
为待监控表设置了审计列之后就无法直接更改了。如果列有变动比较麻烦,需要先完全移除审计组的设置,然后从审计表开始重新设置。
此外,前台界面移除审计组,并运行” 审计线索更新表”请求后,原先新建的shadow表和trigger并不会自动被移除,也就是说审计功能还是启用的,trigger还在将每一个更新动作记录在shadow表中。
因此遇到审计列需要变化的时候,需要手动drop掉相关的shadow表和监控表的一系列trigger。然后重新建立审计设置。
建议设置前详细计划,仔细考虑待监控的表和列,因为如果设置好再改实在是很麻烦的一件事。
4.
审计线索shadow表对null值更新的记录方式
审计线索的记录方法是,每次更新审计表T前,在T的shadow表T_A中新建一行,将表T的待更改列C1,C2……,更改前的值记录入shadow表的相应列之中,未更新的字段留空,这样达到了监控A变化过程的目的。
然而这样的记录方式有一个问题,对于原先为空的值,shadow表中新建了一行,但将更新前的值记录入表中的时候,还是写一个null进去(因为更新前就是null),导致这类更新字段无法通过正常的方式与其他未更新字段(shadow表留空)区分开来。
为解决这个问题oracle给shadow表多加了1个字段audit_true_nulls。
其值的样子类似这样”NNNNYNNNN”,值的长度对于该表监控的列数,也就是说每一列都在这个字段中有一个对应的标志位。经过测试,对应关系就是shadow表的建表列顺序,即第一个标志字符对应shadow表的第一个监控列。
对应的标志位值为Y的时候,表示虽然审计行中该列的值为null,但是本次确实有对该列做更新,只不过该列原本就是null值。
这种记录方式可以说是比较不方便程序开发的,因为需要通过两个口径来确认某一列这次确实有或者没有更改,而shadow表记录了新建更改删除的所有动作,其数据量一般是监控表的几倍,写程序的时候要注意效率问题。
另外一个不方便的地方是,如果未来监控列需要更改,则audit_true_nulls的值的字段长度可能会增加或减少,每个标志位对应的值可能也会改变。比如之前第一个标志位表示日记账描述列是否由null值到其他值的更改,修改涉及的监控列后,这样的对应关系可能就被破坏掉了,程序也需要重新修正。
这里有一个一劳永逸解决以上所有问题的方法:监控所有的列。