我正在运行 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;
Run Code Online (Sandbox Code Playgroud)
根据我所读到的内容,处理此问题的最佳方法是创建重复表,每个表只有两个额外字段:
ModifiedDateTime
Action
Run Code Online (Sandbox Code Playgroud)
这真的是最好的方法吗?每次即使对记录进行最轻微的更改,整个记录都会插入到其相应的历史记录表中。这似乎是对空间的巨大浪费。有一个更好的方法吗?
它可能会或可能不会浪费空间取决于对表的典型操作。ForINSERT
并且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);
Run Code Online (Sandbox Code Playgroud)
并在每次更新后将记录添加到这些表中。这里的问题是,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
$$$
Run Code Online (Sandbox Code Playgroud)
一种简单的方法是
在 MySQL 中启用日志记录:
在 mysql 后端控制台中键入以下内容。
SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 'ON';
Run Code Online (Sandbox Code Playgroud)
通过查询检查更新:(您可以根据需要对其进行自定义)
select argument from mysql.general_log where argument REGEXP '*INSERT*';
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
23936 次 |
最近记录: |