Отслеживание изменений в базе данных MySQL - PullRequest
2 голосов
/ 29 апреля 2011

Я использую MySQL 5.1.36, и у меня есть база данных, используемая для системы поддержки через Интернет. В базе данных есть три таблицы, для которых я хочу отслеживать изменения:

CREATE TABLE IF NOT EXISTS `tickets` (
  `TicketNum` int(11) unsigned NOT NULL,
  `SubmittedFromIP` tinyblob,
  `SubmittedFromDevice` varchar(255) DEFAULT NULL,
  `EntryDate` datetime DEFAULT NULL,
  `ClosedDate` datetime DEFAULT NULL,
  `LastName` varchar(50) DEFAULT NULL,
  `FirstName` varchar(50) DEFAULT NULL,
  `Email` varchar(50) DEFAULT NULL,
  `Location` varchar(4) DEFAULT NULL,
  `InventoryNumber` varchar(50) DEFAULT NULL,
  `DeviceName` varchar(50) DEFAULT NULL,
  `Description` text,
  `Notes` text,
  `Agent_ID` smallint(5) unsigned NOT NULL DEFAULT '1',
  `TotalHoursSpent` float NOT NULL DEFAULT '0',
  `Status` smallint(5) unsigned NOT NULL DEFAULT '1',
  `Priority` tinyint(4) NOT NULL DEFAULT '0',
  `LastUpdatedByAgent_ID` smallint(5) unsigned DEFAULT NULL,
  PRIMARY KEY (`TicketNum`),
  KEY `ClosedDate` (`ClosedDate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `ticketsolutions` (
  `Entry_ID` int(10) unsigned NOT NULL,
  `TicketNum` mediumint(8) unsigned DEFAULT NULL,
  `EntryDateTime` datetime DEFAULT NULL,
  `HoursSpent` float DEFAULT NULL,
  `Agent_ID` smallint(5) unsigned DEFAULT NULL,
  `EntryText` text,
  `LastUpdatedByAgent_ID` smallint(5) unsigned DEFAULT NULL,
  PRIMARY KEY (`Entry_ID`),
  KEY `TicketNum` (`TicketNum`),
  KEY `EntryDateTime` (`EntryDateTime`),
  KEY `HoursSpent` (`HoursSpent`),
  KEY `Rating` (`Rating`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `tickettagsmap` (
  `TicketNum` int(11) unsigned NOT NULL,
  `Tag_ID` int(10) unsigned NOT NULL,
  `AddedByAgent_ID` smallint(5) unsigned NOT NULL,
  `DateTimeAdded` datetime NOT NULL,
  PRIMARY KEY (`TicketNum`,`Tag_ID`),
  KEY `Tag_ID` (`Tag_ID`),
  KEY `fk_AgentID` (`AddedByAgent_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Исходя из того, что я прочитал, лучший способ справиться с этим - создать дублирующиеся таблицы, только с двумя дополнительными полями на таблицу:

ModifiedDateTime
Action

Это действительно лучший способ? Каждый раз, когда в запись вносится даже малейшее изменение, вся запись вставляется в соответствующую таблицу истории. Это похоже на огромную трату пространства. Есть ли лучший способ сделать это?

Ответы [ 3 ]

4 голосов
/ 29 апреля 2011

Это может быть или не быть пустой тратой пространства, зависит от типичных операций с таблицами. Для INSERT и DELETE единственный способ отследить это сохранить все значения столбцов. Только для UPDATE вы можете сэкономить место. Вы можете создать 2 таблицы, например,

update_history_main(id int not null auto_increment primary key,
modify_date datetime not null,
table_involved varchar(50) not null);

update_history_details (id int not null auto_increment primary key,
update_history_main_id int not null,
field_name varchar(100),
old_value varchar(100),
new_value varchar(100),
FOREIGN KEY (update_history_main_id) REFERENCES update_history_main(id)
ON UPDATE CASCADE ON DELETE CASCADE);

и добавляйте записи в эти таблицы после каждого обновления. Проблема в том, что столбцы old_value и new_value должны быть достаточно большими, чтобы сохранить значение любого столбца из ваших исходных таблиц. Поэтому вам, вероятно, нужно создать еще один update_history_details_text_blobs, который будет отслеживать только изменения в столбцах text / blob.

Обновление . Таким образом, тело вашего триггера после обновления для таблицы tickets может выглядеть как

DELIMITER $$$
 CREATE TRIGGER afterTicketUpdate AFTER UPDATE ON tickets
 FOR EACH ROW
 BEGIN
     DECLARE main_id int;
     INSERT INTO update_history_main(modify_date, table_involved) 
      VALUES(NOW(),'tickets';
     SELECT LAST_INSERT_ID() INTO main_id;

     IF (new.SubmittedFromDevice != old.SubmittedFromDevice) THEN
      INSERT INTO update_history_details(update_history_main_id, field_name, 
      old_value,new_value) 
     VALUES (main_id, 'SubmittedFromDevice',old.SubmittedFromDevice,
        new.SubmittedFromDevice);
     END IF; // ... check all other fields. 
 END
$$$
1 голос
/ 04 декабря 2017

Один простой способ сделать это -

  1. Включить ведение журнала MySql.
  2. Проверить наличие обновлений в журналах.

Включить ведение журналав MySQL:

Введите следующее в бэкэнд-консоли mysql.

SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 'ON';

Проверьте наличие обновлений с запросами: (вы можете настроить это по своему усмотрению)

select argument from mysql.general_log where argument REGEXP '*INSERT*';
0 голосов
/ 29 апреля 2011

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

TicketNum          
ModifiedDateTime   
Action

и обновляться триггером каждый раз при необходимости.

...