mysql(几乎)完成审计

时间:2010-09-28 20:35:55

标签: php mysql audit auditing

我正在寻找一种为我的表制作简单事件日志的方法。我有几个表可以被各种用户更改,我想跟踪:

- 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个不同的函数(插入,更新,删除),并在进行查询之前,检查更改内容并生成日志然后运行查询。但是从这里看起来似乎非常缓慢和复杂。

还有另一种更好的方式吗?

由于


好的,我再次检查了触发器,而不是我要找的东西,所以我编写了简单的函数,如果新值不同,将检查要记录的每个查询,如果是,则记录它。 / p>

主要问题是,我没有测量它,但它显然较慢。

首先你需要制作一个新的mysql表,如下所示:

  • id(a_i,primary)
  • creation_date(datetime)
  • user_id(int)
  • table_name(tinytext)
  • record_id(int)
  • cell_name(tinytext)
  • action_type(tinytext)
  • old_value(text)
  • new_value(text)

之后,编写函数。我还没有写“插入”和“删除”部分,但我认为我应该更容易。

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

1 个答案:

答案 0 :(得分:1)

嗯,我也在想这个。

  • 对于我个人来说,每张桌子都有一张桌子可以保留相应的修改,但是嘿。
  • 用户名可以保存在我认为的用户定义变量中(在会话开始后发出类似SET @user='someone'的内容,并使用它。
  • 只要在INSERT,UPDATE和DELETE之后有触发器,获取上一个/下一个值是一个简单的查询,我只会存储OLD值。

简而言之,对于带有coluns(a,b,c)的表,我将创建一个包含列的表(user_id,modtime,a,b,c)。

主要缺点:

  • 批量更新(因此请选择您的表格以便仔细修改)
  • 数据重复豪华,你/我必须有足够的存储空间
  • '相关'数据不会触发修订(即:更改group_members表并不会真正改变groups表,而您可能希望将其保留为groups表的时间点{ {1}}而不是深入研究group_members改动。

总而言之,这对我来说似乎很划算,但是由于我在实践中很少看到它,必须是令人信服的理由,为什么它不好,所以我会等待那些答案。