2011-04-29 95 views
2

我正在运行MySQL 5.1.36并且有一个用于基于Web的帮助台系统的数据库。该数据库有三个表我想跟踪更改:跟踪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 2011-04-29 15:40:53

+0

我想知道什么时候_anything_会随着票证发生变化。例如,如果用户提交的问题描述较差,则代理会更新描述以更好地描述问题。不过,我仍然想看看原始描述是什么。我还想跟踪票证的优先顺序何时更改,何时将标签添加到票证中,何时更改票证的状态等。 – Paul 2011-04-29 15:49:57

+0

如果您想恢复某些内容以查看更改之前的状态,则必须存储您已知道如何执行的完整数据。 – Johan 2011-04-29 16:01:12

回答

4

它可能会或可能不会浪费空间取决于典型的表操作。对于INSERTDELETE,唯一的方法是存储所有列值。只有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_valuenew_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建议将blob中的更改存储在单独的表中,并仅在更改时存储这些更改。 – Johan 2011-04-29 16:02:06

+1

谢谢,这是一个不错的主意。不过,我不知道这些查询会如何查找。看起来它可能非常复杂。我将不得不玩弄它。 – Paul 2011-04-29 16:03:06

+0

我添加了一个可用于填充历史数据的触发器示例(原始草稿,您还需要在包含可空列的条件中处理NULL值) – a1ex07 2011-04-29 16:28:01

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*';