The goal of this post is to build a prototype that demonstrates the auditing capabilities of Flashback Data Archive in Oracle 12c.
Although the documentation mentions that Flashback Data Archive provides the ability to track and store transactional changes to a table I was struggling to see how this functionality actually worked and what audit information was available hence my need to build something that I could test drive.
This post is not a deep dive into Flashback Data Archive for that I would refer you to the landing page of Flashback Data Archive within the documentation.
The prototype was developed using the pre-built developer app vm for virtual box which at the time of writing used Oracle database version 18.104.22.168.
The goal of the demo is show how a table is audited for changes, the audit will show who changed the record and when the change was made.
Creating the prototype is split into the following steps:
- Create a new user (optional).
- Creation of a table that you wish to audit changes to.
- Creation of the Flashback Data Archive objects.
- Creation of a new context and the dependent package.
- Executing DML statements against the table of interest.
- Viewing the audit information.
Create a new user (optional).
Logging on as a user with SYSDBA role, create a new user called: fda_user
create user fda_user identified by fda_user; alter user fda_user quota unlimited on users;
fda_user is then given the following grants:
grant create table to fda_user; grant alter user to fda_user; grant alter session to fda_user; grant create session to fda_user; grant create any context to fda_user; grant create procedure to fda_user;
Creation of a table that you wish to audit changes to.
For this prototype I am using a copy of the employees table owned by the HR user. The command below was run using whilst logged in with the SYSDBA role.
create table fda_user.employees as select * from hr.employees;
Creation of the Flashback Data Archive objects.
Still logged in as a user with SYSDBA role create a new tablespace and allow the fda_user to utilise it.
create tablespace fda2 datafile 'FDA2.dbf' size 1M autoextend on next 1M; alter user fda_user quota unlimited on fda2;
The next step is to create the Flashback Data Archive. In this example the audit information will be kept for 1 year and then automatically purged.
create flashback archive fda_one_year_data tablespace fda2 quota 1G retention 1 year;
Next the fda_user is granted permissions in order to utilise Flashback Data Archive.
grant flashback archive on fda_one_year_data to fda_user; grant execute on dbms_flashback_archive to fda_user;
In the file step with the sysdba role, the table that is to be audited, employees is pointed to the Flashback Data Archive that was created earlier.
alter table fda_user.employees flashback archive fda_one_year_data;
Creation of a new context and the dependent package.
Log in to the database as the fda_user create the following context and PL/SQL package spec and body. This will used to assign who made the changes to the Employees table what those changes where.
CREATE OR REPLACE CONTEXT employee_context USING employee_ctx_api;
CREATE OR REPLACE PACKAGE employee_ctx_api IS PROCEDURE set_value (p_name IN VARCHAR2, p_value IN VARCHAR2); END employee_ctx_api; / CREATE OR REPLACE PACKAGE BODY employee_ctx_api IS PROCEDURE set_value (p_name IN VARCHAR2, p_value IN VARCHAR2) IS BEGIN dbms_session.set_context('employee_context', p_name, p_value); END set_value; END employee_ctx_api; /
For the sake of keeping the example on track the context and dependent package has been created in the same schema but in a production environment both the context and package would live in a different schema.
With this step, the required set up and configuration of Flashback Data Archive is now complete.
Executing DML statements against the table of interest.
In the following statements, a call is made to dbms_session and the package used by our context to record who is making the change and the action they are undertaking. This is then followed by the insert, update or delete statement.
begin dbms_session.set_identifier('Ian'); employee_ctx_api.set_value('action','Insert'); insert into employees ( employee_id, first_name, last_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, department_id ) values ( 9999, 'William', 'Bodie', 'firstname.lastname@example.org', '01-123-456', TO_DATE('01-JAN-1978', 'DD-MON-YYYY'), 'SH_CLERK', '20000', NULL, 149, 80 ); commit; end;
begin dbms_session.set_identifier('Ian'); employee_ctx_api.set_value('action','Update'); update employees e set e.salary = 100009 where e.employee_id = 9999; commit; end;
begin dbms_session.set_identifier('Ian'); employee_ctx_api.set_value('action','Delete'); delete from employees where employee_id = 9999; commit; end;
Viewing the audit information
With committed changes to the Employees table the audit information can be viewed using a Flashback Table Query such as the following:
SELECT employee_id, salary, versions_starttime, versions_endtime, versions_operation vo, DBMS_FLASHBACK_ARCHIVE.get_sys_context(versions_xid, 'USERENV','SESSION_USER') AS session_user, DBMS_FLASHBACK_ARCHIVE.get_sys_context(versions_xid, 'USERENV','CLIENT_IDENTIFIER') AS client_identifier, DBMS_FLASHBACK_ARCHIVE.get_sys_context(versions_xid, 'employee_context','action') AS action FROM employees VERSIONS BETWEEN TIMESTAMP SYSTIMESTAMP-(1/24) AND SYSTIMESTAMP WHERE employee_id = 9999 ORDER BY versions_startscn;
Reviewing the query results shows a record being inserted, updated and finally deleted along with who did it (session_user and client_identifier columns), when it was done (versions_starttime column) and what was done (action column). Although this last column is not really useful as the information is already provided by the versions_operation (vo column) in the screenshot but is included as an example of what can be recorded.
In this post I have shown how you can build a prototype to see if the Audit capabilities of Flashback Data Archive would work with your existing application.
The inspiration for this post came from two sources. First was Connor McDonald’s superb presentation on Flashback Data Archive at the 2015 UKOUG conference and Tim Hall’s fantastic and generous site