mysql (почти) полный аудит

Я ищу способ сделать простой журнал событий для моих таблиц. У меня есть несколько таблиц, которые могут быть изменены разными пользователями, и я хочу отслеживать:

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

somthing как будет здорово:

 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 (вставка, обновление, удаление) и непосредственно перед выполнением запроса, чтобы проверить, что изменилось, и сделать журнал, а затем запустить запрос. Но отсюда это кажется очень медленным и сложным.

Есть ли еще лучший способ?

благодаря


Хорошо, я снова проверил триггеры и не то, что искал, поэтому написал простые функции, которые будут проверять каждый запрос, который вы хотите зарегистрировать, если новые значения разные, и если да, то он записывает его в журнал.

Основная проблема заключается в том, что я ее не измерял, но, очевидно, медленнее.

сначала вам нужно создать новую таблицу mysql следующим образом:

  • id (a_i, первичный)
  • create_date (datetime)
  • user_id (int)
  • table_name (tinytext)
  • record_id (int)
  • cell_name (tinytext)
  • action_type (tinytext)
  • 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_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_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); } с 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); } с 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' 

надеюсь, что это помогает. Он протестирован на данный момент и работает. Если будут обновления, я отправлю его здесь.

аудит - после изменения

Хм, я тоже думал об этом.

  • Наличие таблицы для каждой таблицы для исправлений для меня не будет проблемой для меня лично, но эй.
  • Я думаю, что имя пользователя может храниться с определенными пользователем переменными (после запуска сеанса запускается что-то вроде SET @user='someone' , и используйте это.
  • Так как есть триггеры после INSERT, UPDATE и DELETE, получение предыдущих / следующих значений – простой запрос, я буду хранить только значения OLD.

Короче говоря, для таблицы с coluns (a, b, c) я бы создал таблицу со столбцами (user_id, modtime, a, b, c).

Основные недостатки:

  • пакетные обновления медленны (так что выберите ваши таблицы, чтобы они тщательно сохраняли ревизии)
  • дублирование данных deluxe, у вас / у меня должно быть достаточно места для хранения
  • «связанные» данные не вызывают изменения (т. е. изменение таблицы group_members самом деле не изменяет таблицу groups , в то время как вы можете захотеть сохранить это как точку времени для groups а затем group_members через изменения group_members .

В целом мне это очень нравится, но, поскольку я редко видел это на практике, должны быть веские причины, почему это плохо, поэтому я буду ждать этих ответов.