跟踪MySQL数据库更改

时间:2011-04-29 15:30:59

标签: mysql history

我正在运行MySQL 5.1.36,并且有一个用于基于Web的帮助台系统的数据库。数据库有三个表我想跟踪的变化:

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 个答案:

答案 0 :(得分: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列应该足够大,以保持原始表中任何列的值。因此,您可能需要创建另一个仅跟踪text / blob列中的更改的update_history_details_text_blobs

<强>更新即可。因此,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)

一种简单的方法是

  1. 启用MySql日志记录。
  2. 检查日志中的更新。
  3. 在MySQL中启用日志记录:

    在mysql后端控制台中键入以下内容。

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

    使用查询检查更新:(您可以根据需要对其进行自定义)

    select argument from mysql.general_log where argument REGEXP '*INSERT*';
    

答案 2 :(得分:0)

您可以为每个表创建Triggers,以便在插入,更新或删除数据时运行。您的跟踪表可能会包含以下内容:

TicketNum          
ModifiedDateTime   
Action

每次根据需要通过触发器进行更新。