01Oct
Use flashback data archive instead of journaling tables
By: Hayden Hudson On: October 1, 2021 In: APEX Developer Solutions Comments: 2

This post is directed at Oracle database users and DBAs looking for a recommendation on how to audit their tables. I’m reviewing two common standards:  

(1)  Journaling tables vs. (2) Flashback Data Archive (FDA). 

Ultimately, I recommend using FDA.

(1) Journaling tables

This auditing standard describes adding triggers to the tables you wish to audit to populate a secondary table with a log of all the DML performed against the 1st table. 

How to

An easy way to implement this standard is described in this video: APEX Instant Tips #40 “Instantly” add full table audit capability to your applications

An alternative methodology is described in Connor McDonald’s GitHub repo: connormcd/audit_utility: Automatic generator for the typical audit triggers we have on Oracle tables with lots of options

Review

Pros Cons
  1. No need to request specials grants or privileges from your DBA
  2. Uses basic SQL concepts.
  3. Data can be exported/imported across databases (as with any table).
  1. Audit trail can be edited by database users.
  2. Needs continual maintenance – every time you add/drop a column, you need to make the corresponding change in the trigger.
  3. Clutters your schema with “audit” objects (triggers and tables).
  4. Triggers can impact performance.

 

(2) Flashback Data Archive

This auditing standard describes enabling an Oracle Database feature to preserve a history of all the changes performed against the tables you wish to audit.

How to

We discuss the following instructions in our episode  APEX Instant Tips #43 Flashback Data Archive.

DBA steps

You will need to involve your DBA to get started. I recommend that a DBA perform the following:

1 . Create a tablespace for archive data, you can name it ‘archive_data’, for example.

2 . Create an archive in said-tablespace:

create flashback archive default fda1year tablespace archive_data retention 1 year;

The above command defines that all audit data will be preserved for a duration of 1 year, then purged. Consult your legal team for what your retention period should be.

3 . Instruct FDA to store context data (like APP_USER, SESSION_USER and CLIENT_IDENTIFIER) for all archive-enabled tables. This is highly recommended because you need your audit trail to capture the username of the APEX user:

exec dbms_flashback_archive.set_context_level('ALL');

4 . Allow your database user to enable archiving into the default archive:

grant flashback archive on fda1year to hayden;

5 . Allow said-database user to access the context information using dbms_flashback_archive:

grant execute on dbms_flashback_archive to hayden;

Regular database user steps

1 . Thanks to the “flashback archive” grant from your DBA you can now audit any table in your schema, eg:

alter table ait_env_var flashback archive;

2 . To access the context variables that record which APEX users perform DML on your table, I recommend creating a simple package function to catch errors in the event of the context variables being missing:

create or replace package ait_fda authid definer is

  function my_context(p_xid       in raw,
                      p_namespace in varchar2,
                      p_parameter in varchar2)
                      return varchar2;
 
end ait_fda;
create or replace package body ait_fda  is

   function my_context(p_xid       in raw,
                       p_namespace in varchar2,
                       p_parameter in varchar2)
                       return varchar2
   is

   l_context_value varchar2(256);
   fetch_is_null exception;
   pragma exception_init(fetch_is_null, -1405);
   begin
      
       select dbms_flashback_archive.get_sys_context(p_xid, p_namespace, p_parameter)
           into l_context_value
           from dual;
      
       return l_context_value;

   exception
       when fetch_is_null then
           return null;
       when others then
           raise;
   end my_context;
  
end ait_fda;

You can now query the audit history of your table by writing a Flashback version query, eg:

select
  aev.*,   versions_operation,
  versions_startscn,
  versions_starttime,
  versions_endscn,
  versions_endtime,
  versions_xid,
  ait_fda.my_context( p_xid       => versions_xid,
                      p_namespace => 'USERENV',
                      p_parameter => 'SESSION_USER') as session_user,
  ait_fda.my_context( p_xid       => versions_xid,
                      p_namespace => 'USERENV',
                      p_parameter => 'CLIENT_IDENTIFIER') as client_identifier,
  ait_fda.my_context( p_xid       => versions_xid,
                      p_namespace => 'APEX$SESSION',
                      p_parameter => 'APP_USER') as apex_user
from
  ait_env_var
versions between scn minvalue and maxvalue aev

For more on how to write a Flashback version query consult the following post.

Review

Pros Cons
  1. Automatically keeps up with any changes you make to the table (e.g. dropping and adding columns).
  2. Much lower impact on performance relative to a trigger, thanks to asynchronous writes to the history table.
  3. Explicit retention period means that purging old data is automatically taken care of.
  1. You need a DBA’s involvement
  2. Early in the history of the FDA, there were some bugs. However, FDA is being used more and more by both clients and Oracle itself. Recent versions have resolved my concerns about bugs.
  3. You cannot move the audit history with your database using export/import, you must use a PDB or database clone (arguable, this is the flip-side of a feature because it speaks to how your audit trail is less corruptible).

 

Conclusion

All in all, my recommendation is to use your database’s built-in auditing feature: Flashback Data Archive (FDA). It’s the least amount of hassle for the most reliable audit trail. Let me know if you agree or disagree!

Share this:
Share

2 Comments:

    • Jared
    • November 05, 2024
    • Reply

    Hi Hayden, if you do not have a DBA to perform the steps you recommend a DBA perform, especially the creation of a tablespace, how would you recommend going about creating the tablespace? What I would like to accomplish is to create a tablespace that is solely for the purpose of my FDA, and in which the space grows as necessary to store all change data during the defined retention period (i.e. 1 year or 5 years or whatever). I have been referencing the documentation on CREATE TABLESPACE (12.2), but not being a DBA and not having an in-house DBA, it has been somewhat difficult to definitively plan out a tablespace that I know would work well for an FDA, given the desires I mention above. I had hoped I wouldn’t have to be monitoring this very often, if at all, and I also don’t want data to not be tracked in my defined retention period if it goes beyond a specified amount of storage. We have plenty of space, and if that did become a concern, we could perhaps revisit the tablespace/FDA definition.

    Basically, my question is, can you elaborate on the points that you mention would normally belong to a DBA, to someone who is not a DBA, but a Developer?

    Thank you!

      • Anton Nielsen
      • November 06, 2024
      • Reply

      Hi Jared,

      The key is that you must have the CREATE TABLESPACE system privilege. A DBA will need to grant you that privilege, for example:
      grant CREATE TABLESPACE to JARED;

      Once you have that privilege, you can create a tablespace. You still need to know the details, though, so you would need some knowledge of how the database is installed and configured. The basic create tablespace command is

      CREATE TABLESPACE fda_tablespace
      DATAFILE ‘/u01/app/oracle/oradata/your_database/fda_datafile01.dbf’ SIZE 1000M
      AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED
      RETENTION GUARANTEE
      FLASHBACK ON;

      Specifically, you need to know where the datafile should exist on the file system. For this reason, a DBA would typically do this step. You may want to increase the initial size (1000M above). I typically set the AUTOEXTEND to about 10% of the initial size. It really depends on how much your data changes, though.

      Hopefully points you in the right direction.

      Anton

Leave reply:

Your email address will not be published. Required fields are marked *