2010-01-06 132 views
118

每次我需要設計一個新的數據庫時,我花了相當一段時間 考慮如何設置數據庫模式以保持審計日誌 的更改。用於審計日誌記錄的數據庫設計

有些問題已經在這裏關於這個要求,但我不同意, 有適合所有情況的一個最好的方法:

我也偶然發現了這個interesting article on Maintaining a Log of Database Changes試圖列出親和EAC的利弊h方法。它寫得非常好,並且有有趣的信息,但它使我的決定變得更加困難。

我的問題是:是否有一個參考,我可以使用,也許一本書或者像一個決策樹可以參考我來決定哪種方式應基於一些 輸入變量我走了,喜歡的東西:

  • 數據庫架構
  • 如何日誌將被查詢
  • 的概率,這將需要重新記錄
  • 什麼是更重要的成熟度:寫入或讀取PE rformance
  • 自然可

,我知道的方法正在被記錄的值(字符串,數字,斑點)

  • 存儲空間爲:

    1.添加列創建修改日期和用戶

    表例如:

    • ID
    • _1
    • _2
    • VALUE_3
    • CREATED_DATE
    • modifed_date
    • CREATED_BY
    • modified_by

    主要缺點:我們失去了改變的歷史。提交後無法回滾。

    2。只能插入表格

    Table example

    • ID
    • _1
    • _2
    • VALUE_3
    • 刪除(布爾)
    • 用戶

    主要缺點:如何讓外鍵保持最新狀態?巨大的空間需要

    3.爲每個表

    歷史表的例子創建一個單獨的歷史表:

    • ID
    • _1
    • _2
    • VALUE_3
    • VALUE_4
    • 用戶
    • 刪除(布爾)
    • 時間戳

    主要缺點:需要複製所有審計表。如果模式更改,則還需要遷移所有日誌。

    4.創建一個統一的歷史表中所有的表

    歷史表的例子:

    • table_name的
    • 用戶
    • NEW_VALUE
    • 刪除(布爾)
    • 時間戳

    主要缺點:如果需要,我能否重新創建記錄(回滾)? new_value列需要是一個巨大的字符串,因此它可以支持所有不同的列類型。

  • +0

    相關:http://stackoverflow.com/questions/9852703/store-all-data-changes-with-every-details-stackoverflow-like – Kaii 2012-03-24 23:57:55

    +0

    以及使用歷史數據庫,而不是表的是什麼? – Jowen 2015-01-26 14:01:17

    +0

    也許你可以檢查https://github.com/airblade/paper_trail的設計 – zx1986 2016-07-08 13:08:35

    回答

    72

    少數維基平臺使用的一種方法是分隔您正在審覈的識別數據和內容。它增加了複雜性,但是最終會得到完整記錄的審計跟蹤,而不僅僅是已編輯的字段列表,您必須將其混合起來以便讓用戶瞭解舊記錄的樣子。

    因此,舉例來說,如果你有一臺名爲機會跟蹤銷售交易,你實際上創建兩個單獨的表:

    機會
    Opportunities_Content(或類似的東西)

    機會表中將包含您將用於唯一標識記錄的信息,幷包含您爲f引用的主鍵外匯關鍵關係。 Opportunities_Content表將包含用戶可以更改的所有字段,並且您希望爲其保留審計線索。 Content表中的每個記錄都將包含其自己的PK以及修改日期和修改日期數據。 機會表將包括對當前版本的引用以及有關何時創建主記錄以及由誰創建的信息。

    這裏有一個簡單的例子:

    CREATE TABLE dbo.Page( 
        ID int PRIMARY KEY, 
        Name nvarchar(200) NOT NULL, 
        CreatedByName nvarchar(100) NOT NULL, 
        CurrentRevision int NOT NULL, 
        CreatedDateTime datetime NOT NULL 
    

    而且內容:

    CREATE TABLE dbo.PageContent(
        PageID int NOT NULL, 
        Revision int NOT NULL, 
        Title nvarchar(200) NOT NULL, 
        User nvarchar(100) NOT NULL, 
        LastModified datetime NOT NULL, 
        Comment nvarchar(300) NULL, 
        Content nvarchar(max) NOT NULL, 
        Description nvarchar(200) NULL 
    

    我很可能會令內容表的PK從PAGEID多列鍵和修訂提供了修訂的身份類型。您將使用修訂列作爲FK。然後你通過JOINing這樣拉取綜合記錄:

    SELECT * FROM Page 
    JOIN PageContent ON CurrentRevision = Revision AND ID = PageID 
    

    有可能有一些錯誤在那裏......這是我的頭頂。但它應該給你一個替代模式的想法。

    Josh

    +5

    downvote的任何原因? – 2012-05-08 18:30:54

    +8

    關於審計方法,但對於生產而言,需要花費大量時間爲數據庫中的每個表開發單獨的審計表,爲每個表編寫觸發器以捕獲更改並將其寫入審計表。此外,由於每個審計表的結構不同,因此在爲所有表制定單一審計報告方面存在巨大挑戰。 – 2013-11-21 17:47:53

    +9

    如果爲每個表編寫和維護腳本是一個有意管理審計數據庫的組織,那麼我自然會建議他們聘請一位經驗豐富的DBA或者具有足夠經驗的高度靈活且經驗豐富的軟件工程師來創建審計數據庫。 – Hardryv 2015-04-01 17:07:44

    6

    我不知道有任何參考,但我確定有人寫了一些東西。

    但是,如果目的只是爲了有發生的事情,最典型的使用審計的記錄日誌,那麼爲什麼不乾脆讓一切:

    timestamp 
    username 
    ip_address 
    procedureName (if called from a stored procedure) 
    database 
    table 
    field 
    accesstype (insert, delete, modify) 
    oldvalue 
    newvalue 
    

    據推測,這是由觸發器維護。

    +0

    你甚至可以做一個簡單的:(時間戳,用戶,SQL命令)。 – 2010-01-06 18:42:00

    +0

    我不知道有什麼方法可以在數據庫服務器中獲取它,但當然可以很容易地從外部完成。 – wallyk 2010-01-06 18:50:54

    +2

    在我看來,這是與原始問題中顯示的第4個選項相同的設計模式。 – givanse 2014-02-10 05:11:22

    10

    如果您使用的是SQL Server 2008,那麼您可能應該考慮更改數據捕獲。這是2008年的新功能,可以爲您節省大量的工作。

    +0

    這裏更多的信息:http://msdn.microsoft.com/en-us/library/cc645858.aspx – RedFilter 2010-01-06 21:12:49

    +0

    這裏是鏈接到SQL 2012更改跟蹤信息。 http://msdn.microsoft.com/en-us/library/bb933994.aspx +1使用內置的功能,沒有點重新發明輪子。 – Chris 2013-02-05 20:19:38

    +2

    @Chris你有沒有使用它自己?事實上,它可以追蹤所有內容......但是能夠從中獲得有用的信息是另一回事。我的自行車不能使用拖拉機輪。 – Jowen 2015-03-25 11:27:46

    3

    我認爲沒有什麼像決策樹。由於一些優點和缺點(或要求)不是真正可數的。你如何衡量成熟度?

    因此,只需將您的審計日誌的業務需求排成一行。嘗試預測這些要求將來如何變化併產生技術要求。現在你可以比較它的優點和缺點,並選擇正確/最好的選擇。

    而且可以放心,不管你怎麼決定,總有人會認爲你做出了錯誤的決定。然而,你做了功課,你證明了你的決定是正確的。

    1

    我們將爲博客應用程序創建一個小示例數據庫。兩個表是必需的:

    blog:存儲唯一帖子ID,標題,內容,以及刪除標誌。 audit:存儲一組基本的與記錄的ID改變的日期/時間的歷史變化,博客文章ID,變化類型(NEW,編輯或刪除)和。 下面的SQL創建blog和索引中刪除列:

    CREATE TABLE `blog` (
        `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 
        `title` text, 
        `content` text, 
        `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', 
        PRIMARY KEY (`id`), 
        KEY `ix_deleted` (`deleted`) 
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Blog posts'; 
    

    下面的SQL創建audit表。所有列都被編入索引,併爲引用blog.id的audit.blog_id定義一個外鍵。因此,當我們實際刪除博客條目時,它的全部審計歷史記錄也會被刪除。

    CREATE TABLE `audit` (
        `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 
        `blog_id` mediumint(8) unsigned NOT NULL, 
        `changetype` enum('NEW','EDIT','DELETE') NOT NULL, 
        `changetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
        PRIMARY KEY (`id`), 
        KEY `ix_blog_id` (`blog_id`), 
        KEY `ix_changetype` (`changetype`), 
        KEY `ix_changetime` (`changetime`), 
        CONSTRAINT `FK_audit_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `blog` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;