3

テーブルの簡単なイベント ログを作成する方法を探しています。さまざまなユーザーが変更できるテーブルがほとんどないので、追跡したいと思います。

- 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 (日時)
  • ユーザー ID (整数)
  • テーブル名 (小さなテキスト)
  • record_id (整数)
  • cell_name (小さなテキスト)
  • action_type (小さなテキスト)
  • 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'

これが役に立てば幸いです。今のところテスト済みで動作します。更新がある場合は、ここに投稿します。

監査 - 変更後

4

1 に答える 1

1

うーん、私もこれについて考えていました。

  • テーブルごとにテーブルを保持するためのリビジョンを作成することは、個人的にはそれほど問題にはなりませんが、ちょっと。
  • ユーザー名は、私が信じるユーザー定義変数で保持できます(セッション開始後、のようなものを発行しSET @user='someone'、それを使用します。
  • INSERT、UPDATE、およびDELETEの後にトリガーがある限り、前/次の値を取得するのは簡単なクエリであり、OLD値のみを保存します。

つまり、列(a、b、c)を持つテーブルの場合、列(user_id、modtime、a、b、c)を持つテーブルを作成します。

主な欠点:

  • バッチ更新は遅いです(したがって、慎重にリビジョンを保持するようにテーブルを選択してください)
  • データ重複排除デラックス、あなたは/私は十分なストレージスペースを持っている必要があります
  • 「関連する」データはリビジョンをトリガーしません(つまり、group_membersテーブルを変更しても実際にはテーブルは変更されませんが、変更を詳しく調べるのではなくgroups、ある時点として保持することをお勧めします。groupsgroup_members

全体的に見て、それは私には良いことのように思えますが、実際にはめったに見たことがないので、それが悪い理由は説得力があるに違いないので、それらの答えを待ちます。

于 2010-09-28T20:52:18.397 に答える