2010-09-28 48 views
3

我正在尋找一種爲我的表製作簡單事件日誌的方法。我有一個可以通過各種用戶更改幾張桌子,我想繼續跟蹤:mysql(幾乎)完成審計

- who made the change 
- when 
- what was before update 
- what is the new value 
- which table and which record & column 

財產以後像將是巨大的:

20:00:00 | john | update | products | 113 | product_name | "xbox" | "xbox 360" 
20:00:10 | jim | update | products | 113 | product_name | "xbox 360" | "" 
20:01:00 | jim | delete | products | 113 

所以我讀的觸發可能是答案,但據我看來,似乎我需要爲每一列我想跟蹤一個完整的新表。觸發器對於這項工作來說也不完美,因爲我想記錄是誰做出了改變,並且從我讀到的內容來看這是不可能的。

我想爲CRUD(插入,更新,刪除)製作3個不同的函數,並且在進行查詢之前,檢查更改內容以及創建日誌然後運行查詢。但從這裏來看,它似乎非常緩慢和複雜。

還有更好的方法嗎?

感謝


好吧,我檢查再次觸發其不是我所尋找的,所以我寫了簡單的功能,將檢查要記錄如果新的值是不同的每個查詢,如果是這樣 - 它會記錄它。

主要問題是,我沒有測量它,但它顯然比較慢。

首先你需要一個新的MySQL表如下:

  • ID(A_I,初級)
  • CREATION_DATE(日期時間)
  • USER_ID(INT)
  • 表名(TINYTEXT)
  • record_id(int)
  • cell_name(tinytext)
  • action_type(tinyte XT)
  • OLD_VALUE(文本)
  • NEW_VALUE(文本)

後,寫的功能。我沒有寫'INSERT'和'DELETE'部分,但我認爲我應該更容易。

function log_query($action_type, $table, $values, $parameters){ 

if ($action_type == 'UPDATE'){ 

    log_updates($action_type, $table, $values, $parameters); 

    $query = "UPDATE $table SET "; 
    foreach ($values as $key => $value){ 
     $query .= $key."='"; 
     $query .= $value."', "; 
    } 
    unset($value); 

    $query = substr($query, 0, -2); 

    $query .= ' WHERE '; 

    foreach ($parameters as $key => $value){ 
     $query .= $key."='"; 
     $query .= $value."' AND "; 
    } 
    unset($value); 

    $query = substr($query, 0, -4); 

    $result = mysql_query($query); 

    } 
} 

和:

function log_updates($action_type, $table, $values, $parameters){ 
$where = " WHERE "; 
$user_id = '1234'; //example 
foreach ($parameters as $key => $value){ 
     $where .= $key."='"; 
     $where .= $value."' AND "; 
} 
unset($value); 

$where = substr($where, 0, -4); 

foreach ($values as $key => $value){ 
    $result = mysql_query("SELECT $key, id FROM $table $where"); 

    $row = mysql_fetch_row($result); 
    $old_value = $row[0]; 
    $record_id = $row[1]; 

    if ($action_type == 'UPDATE'){ 
     if ($old_value != $value){ 
      $logger = mysql_query("INSERT INTO auditing (event_date, action_type, user_id, table_name, record_id, cell_name, old_value, new_value) 
            VALUES (NOW(), '$action_type', $user_id, '$table', '$record_id', '$key', '$old_value', '$value')"); 
      if (!$logger) echo mysql_error(); 
     } 
    } 


    } 
    unset($value); 

} 

打電話給你需要首先命令參數查找特定行的功能,新的值將數組,之後調用log_query功能:

$update = Array('name' => 'barbara', 'description' => 'new name'); 
$parameters = Array('id' => '1', 'name' => 'barbi'); 
log_query('UPDATE', 'checktable', $update, $parameters); 

這將真實地檢查'姓名'是否發生了變化以及描述是否被更改。對於每一個,如果它發生變化,它會在「審計」表中插入新記錄,指定確切的變化。在記錄更改後,它將運行更新查詢 。在我們的例子中:

UPDATE checktable SET name='barbara', description='new name' WHERE id='1' AND name='barbi' 

希望這有助於。它測試了現在和工作。如果有更新 - 我會在這裏發佈。

audit - after the change

+0

有關哪個用戶使觸發器觸發IS的可用信息。請參閱:http://dev.mysql.com/doc/mysql-security-excerpt/5.7/en/account-activity-auditing.html – Bampfer 2015-09-15 16:47:53

回答

1

嗯,我也在想這個問題。

  • 有每桌對保持一個修訂表不會是太大的問題,對我個人,但嘿。
  • 用戶名可以保持與用戶定義的變量,我相信,(會話啓動的問題類似SET @user='someone'後,並使用它。
  • 作爲多頭因爲有後INSERT,UPDATE觸發器和DELETE,得到了一個/下一個值是一個簡單的查詢,我只會存儲OLD值

簡而言之,對於具有coluns(a,b,c)的表,我會創建一個列(user_id,modtime,a ,b,c)

主要缺點:

  • 批量更新(所以選擇你的表保留了認真修訂)
  • 數據複製的豪華,你/我必須有足夠的存儲空間
  • 「相關」數據不會觸發一個修訂(即:修改一個group_members表並不會真正改變一個groups表,但您可能希望將其保留爲groups的一個時間點,而不是通過group_members修改。

所有的一切似乎很划算給我,但我已經罕在實踐中看到它有必須是令人信服的理由,爲什麼它的壞,所以我會等待着這些問題的答案。

+0

首先感謝您的回答。我認爲你指出了我的研究有了突破。我不知道用戶定義的變量!用戶定義的變量和下面的文章可能是完美的答案:http://streetsmartingit.blogspot.com/2008/04/using-mysql-triggers-to-audit-field.html – 2010-09-29 07:04:08

+0

好吧,我想到了一個elegeant(還較慢)解決方案。 - 見下文 – 2010-09-29 08:13:03