2010-09-28 118 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

相关问题