Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ideas on database design for capturing audit trails [closed]

How can I maintain a log of the data in my DB?

I have to maintain a log of every change made to each row. That means that I can't allow DELETE and UPDATE to be performed.

How can I keep such a log?

like image 977
Greens Avatar asked Jun 26 '09 21:06

Greens


People also ask

How do you create an audit trail in a database?

To generate audit trails in shadow tables, the safest option is to create insert, update and delete triggers, that for each affected record in the original table generate a record in the audit table. The triggers should have access to all the audit information you need to record in the shadow table.

What should I capture in an audit trail?

An audit trail should include the information needed to establish what events occurred and what person or system caused them. That event record would then specify when it happened, the user ID associated with it, the program or command that initiated the event, and the result.

What is a database audit trail?

When you audit a database, each operation on the data can be monitored and logged to an audit trail, including information about which database object or data record was touched, what account performed the action and when the activity occurred. However, not all audit logs have the same value to the auditors.


2 Answers

Use "Insert Only Databases"

The basic idea is that you never update or delete data.

Each table has 2 datetime columns from and to.

They start with the value null in each (beginning of time to end of time)

When you need to "change" the row you add a new row, at the same time you update the to in the previous row to Now and the from in the row you are adding to Now.

You read data out of the table via a view that has a where to = null in it.

This method also gives you a picture of the state of your database at any point in time.

EDIT

Just to clarify in response to the comment: The sequence would be given by the primary key of the table, which would be an autoincrement number.

like image 132
Shiraz Bhaiji Avatar answered Nov 09 '22 07:11

Shiraz Bhaiji


Use an "insert only" database, as described by Shiraz Bhaji, but you can use a simpler technique. For each table that you need to maintain audit data for, just have an additional column for Updated Time, defaulting to now. When you make a change to a record, instead of updating, just do an insert with all your data; the UpdatedTime column will get the current time.

Note that this method means you have to break or reconsider your UNIQUE constraints; you can keep a primary key, but the uniqueness becomes a composite of your primary key and your UpdatedTime.

This technique has the advantage of giving you a known range of historical data for each record on the table (each record is valid for a given time if it is the TOP 1 of records WHERE TimeOfInterest > UpdatedTime ORDER BY UpdatedTime DESC) with a low overhead (just a single column on the table). It's also quite amenable to conversion from tables not using this method, with a simple ALTER TABLE to add a single column (which you can name consistently). Then you just need to alter your UNIQUE constraints to use a composite of their current contraints and the UpdatedTime column, and some queries will need to be altered.

Note as well that you can actually avoid converting all of your queries if you create a view of the table that simply returns the most recent entry for each of the records; you end up with a table which maintains historical data transparently, and a view which looks like a regular table without the changelogging.

like image 40
Paul Sonier Avatar answered Nov 09 '22 08:11

Paul Sonier