开发者

Is there a best practice for maintaining history in a database?

I don't do database work that often so this is totally unfamiliar territory for me.

I have a table开发者_运维问答 with a bunch of records that users can update. However, I now want to keep a history of their changes just in case they want to rollback. Rollback in this case is not the db rollback but more like revert changes two weeks later when they realized that they made a mistake. The distinction being that I can't have a transaction do the job.

Is the current practice to use a separate table, or just a flag in the current table?

It's a small database, 5 tables each with < 6 columns, < 1000 rows total.


FROM THIS QUESTION

How to keep history of record updates in MySQL?

One simple way to keep version history is to create basically an identical table (eg. with _version suffix). Both of the tables would have a version field, which for the main table you increment for every update you do. The version table would have a composite primary key on (id, version).

Whenever you do an update on the actual table, you also INSERT a new row in the version table with duplicate data. Whenever you want to find the version history, all you need to do is something such as SELECT * FROM content_version WHERE id = CONTENT_ID ORDER BY version.

If you use something like Doctrine ORM, it has a behavior that does this for you automatically via event listeners. You can check it out here: http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors#core-behaviors:versionable

OR

The easiest solution (depending on your specific needs) would probably be to add an on update/insert/delete trigger to your table, so you can perform extra logging when data is inserted/updated/deleted. That way even manual interventions on the db will be covered...

Check http://dev.mysql.com/doc/refman/5.1/en/triggers.html for more information.


Frustrated's answer is one solution - another is an audit table that records the changes, when, and by whom. It's really a question of approach. If performance on your application tables is critical, and they could grow massively using an 'active row' approach, then the audit table is better, as it would separate the history from the active stuff (and I would hope that fixing user errors is less common than 'normal' transactions).


I would recommend a second table. A super simple and easy way would be to duplicate the schema of each table and a Date/Time Stamp column and "ModifiedByUserID" column that will store what the original data was.

Alternatively if users are not modifying a lot of records in the same row at one time you could save space and get a better view of what's happening by making the schema below:

ChangesTable

ChangeID 
[TABLE UNIQUE ID] 
UserName 
Field 
OldValue
NewValue 
CreatedDate


One option is to have all of your tables contain an ID column and a VersionNo column. Then instead of running UPDATES, you insert a new record witht he same ID and an incremented VersionNo.

You can then create a number of views for each of your table that returns just the latest version of each ID to make your Queries easier to manage.


You could use a timestamp to indicate when the record was created and a status indicator to indicate if the record is "Active" or not.

When they make an update to a record, insert a copy of it as a new record (triggers can keep the timestamps current) and then set the old record status to "Archive" and the new one to "Active". If you want, you can also have other audit fields such as "Last Updated timestamp", "Date Archived", "Date Unarchived" (for when you rollback), "Created by User", "Last Modified by User",... If you want a complete history of auditing, you'd need a separate audit table.

Rolling back is simply choosing a version and marking it as "Active" and the others as "Archive".

There are other schemes that are more flexible but also more complex, but you might not need them.


What about such approach I have a relational database with some tables and build record with a timestamp on the "stack".

For example: assume I create employee table + Car table and in a third table I will record the relation employee <-> car each time it changes (with a date). Of course, this should be supported by a GUI from where I can pick the component (employee and car) of the record that will populate the new table:

first record employee1 <-> car1 : 01/01/2013
then         employee1  <-> car2: 01/06/2013

If I want to know the history, I just ask this table. No need to update anything the history is rolling with changes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜