2011-04-29 6 views
2

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

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 

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

+1

** лучший способ ** в зависимости от ваших потребностей, что вы хотите знать о тех, изменения и для чего вы хотите. – Johan

+0

Я хотел бы знать, когда _anything_ меняется с билетами. Например, если пользователь отправляет билет с плохим описанием проблемы, агент обновит описание, чтобы лучше описать проблему. Я все равно хотел бы посмотреть, что такое оригинальное описание. Я также хотел бы отслеживать, когда изменяется приоритет билета, когда теги добавляются в билет, когда статус билета меняется и т. Д. – Paul

+0

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

ответ

4

Это может быть или не быть пустой зоной, зависит от типичных операций со столами. Для 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

+1 за предложение сохранить изменения в блобах в отдельной таблице и хранить их только при их изменении. – Johan

+1

Спасибо, это неплохая идея. Я не знаю, как запросы будут искать это. Похоже, это может быть чрезвычайно сложно. Мне придется поиграть с ним. – Paul

+0

Я добавил пример триггера, который можно использовать для заполнения данных истории (необработанный черновик, вам также необходимо позаботиться о значениях «NULL» в условиях, которые включают в себя обнуляемые столбцы) – a1ex07

0

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

TicketNum   
ModifiedDateTime 
Action 

и при необходимости обновляться с помощью триггера.

0

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

  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*'; 
Смежные вопросы