我希望在我的应用程序中保留表的每次更新的历史记录。我正在使用Laravel,我知道有一些包可以帮助我,但我看起来干净又快。
我有两个选择:
我的第一个问题是,哪一个更快?
我的第二个问题是: 我应该使用这样的模式并将所有表存储到其中:
CREATE TABLE revisions (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`revisionable_type` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`revisionable_id` INT(11) NOT NULL,
`user_id` INT(11) NULL DEFAULT NULL,
`key` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`old_value` TEXT NULL COLLATE 'utf8_unicode_ci',
`new_value` TEXT NULL COLLATE 'utf8_unicode_ci',
`created_at` TIMESTAMP NULL DEFAULT NULL,
`updated_at` TIMESTAMP NULL DEFAULT NULL
)
或者我应该重新创建每个表的“重复”,例如user_history,并在相应的列上添加历史记录
Users: id, name, surname ...
Users_history: id, user_id, name, surname ...
答案 0 :(得分:1)
这是一个设计决定,因此它取决于您和您的要求。您需要考虑以下事项:
如果用户更改了事务中的记录,则同一用户将同时更改所有受影响的字段。根据您建议的结构,所有这些更改都需要单独输入。
使用您提出的结构确定某个特定记录在给定时间点的样子更加困难,因为您基本上必须从插入中重放该记录的所有更改。
在专业方面,所有更改都存储在一个表中,即使您更改了数据库架构,也不必更改日志记录的结构。
您还必须考虑是否要记录所有表格的更改或仅记录一些选定的表格。
如果要记录的表引用其他表,您还需要考虑如何记录。例如,如果要记录事务,那么您可能有一个事务类型字段和一个单独的事务类型表,其中列出了详细描述以及可能有关每种事务类型的其他信息。如果不再使用事务类型,则可以从事务类型表中删除它,或者它的参数可能会更改。
答案 1 :(得分:0)
鉴于此架构:
CREATE TABLE contacts (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`last_name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`updated_by` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`updated_at` TIMESTAMP NULL DEFAULT NULL
)
我也会创建这个架构:
CREATE TABLE contacts_audit (
`id` INT(10) UNSIGNED NOT NULL,
`first_name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`last_name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`updated_by` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`updated_at` TIMESTAMP NULL DEFAULT NULL,
`action` varchar(255) NOT NULL COLLATE 'utf8_unicode_ci'
)
然后使用这些触发器(希望我的触发器语法不会生锈):
CREATE TRIGGER contacts_audit_insert
AFTER INSERT
ON users FOR EACH ROW
BEGIN
INSERT INTO contacts_audit (id, first_name, last_name, updated_by, updated_at, action) values (NEW.id, NEW.first_name, NEW.last_name, NEW.updated_by, NEW.updated_at, 'insert');
END;
CREATE TRIGGER contacts_audit_update
AFTER UPDATE
ON users FOR EACH ROW
BEGIN
INSERT INTO contacts_audit (id, first_name, last_name, updated_by, updated_at, action) values (NEW.id, NEW.first_name, NEW.last_name, NEW.updated_by, NEW.updated_at, 'update');
END;
CREATE TRIGGER contacts_audit_delete
BEFORE DELETE
ON users FOR EACH ROW
BEGIN
INSERT INTO contacts_audit (id, first_name, last_name, updated_by, updated_at, action) values (OLD.id, OLD.first_name, OLD.last_name, OLD.updated_by, OLD.updated_at, 'delete');
END;
潜在的弊端
如果您使用一个MySQL用户名/密码进行数据库访问并根据MySQL中的users
表对用户进行身份验证,那么在执行任何删除之前,您需要在PHP中执行更新,然后执行删除,以便您可以捕获谁删除了您的记录。
但是,如果您使用MySQL对所有用户进行身份验证,那么您可以在触发器中使用它:注意使用USER()
INSERT INTO contacts_audit (id, first_name, last_name, updated_by, updated_at, action) values (NEW.id, NEW.first_name, NEW.last_name, USER(), NEW.updated_at, 'insert');