简体   繁体   English

跟踪 MySQL 数据库更改

[英]Tracking MySQL Database Changes

I'm running MySQL 5.1.36 and have a database used for a web-based help desk system.我正在运行 MySQL 5.1.36 并且有一个用于基于 Web 的帮助台系统的数据库。 The database has three tables I'd like to track changes for:该数据库有三个我想跟踪更改的表:

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;

Based on what I've read, the best way to handle this is to create duplicate tables, only with two extra fields per table:根据我所阅读的内容,处理此问题的最佳方法是创建重复的表,每个表只有两个额外的字段:

ModifiedDateTime
Action

Is this really the best way?这真的是最好的方法吗? Every time even the slightest change is made to a record, the entire record is inserted into its corresponding history table.每次对记录进行最轻微的更改时,都会将整条记录插入到其对应的历史记录表中。 It seems like a huge waste of space.这似乎是对空间的巨大浪费。 Is there a better way to do this?有一个更好的方法吗?

It may or may not be a waste of space depends on typical operations with tables.它可能会也可能不会浪费空间,这取决于对表的典型操作。 For INSERT and DELETE the only way to track is to store all column values.对于INSERTDELETE ,唯一的跟踪方法是存储所有列值。 Only for UPDATE you can save some space.只有UPDATE才能节省一些空间。 You can create 2 tables, for instance,例如,您可以创建 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);

and add records into these tables after each update.并在每次更新后将记录添加到这些表中。 The problem here is that old_value and new_value columns should be large enough to keep value of any column from your original tables.这里的问题是old_valuenew_value列应该足够大以保留原始表中任何列的值。 So you probably need to create another update_history_details_text_blobs that tracks only changes in text/blob columns.因此,您可能需要创建另一个update_history_details_text_blobs来仅跟踪 text/blob 列中的更改。

Update .更新 Thus, the body of your after update trigger for tickets table may look like因此, 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
$$$

One simple way to do this is一种简单的方法是

  1. Enable MySql logging.启用 MySql 日志记录。
  2. Check for updates in the logs.检查日志中的更新。

Enable logging in MySQL:在 MySQL 中启用日志记录:

Type the following in mysql backend console.在 mysql 后端控制台中键入以下内容。

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

Check for updates with queries: (you can customize this to your need)使用查询检查更新:(您可以根据需要自定义)

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

You can create Triggers for each table, to run when data is inserted, updated, or deleted.您可以为每个表创建触发器,以便在插入、更新或删除数据时运行。 Your tracking tables could then hold something like the following:然后,您的跟踪表可以包含以下内容:

TicketNum          
ModifiedDateTime   
Action

and be updated by the trigger each time as needed.并根据需要由触发器每次更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM