MySQL触发器还是PHP数据审计?

MySQL Trigger or PHP for data audit?

我希望在我的应用程序中保留 table 的每一次更新的历史记录。我正在使用 Laravel,我知道有一些软件包可以帮助我,但我正在寻找干净快速的东西。

我有两个选择:

我的第一个问题是,哪个更快?

我的第二个问题是: 我应该使用这样的架构并将我所有的 table 存储到其中吗:

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
)

或者我应该为每个 table 重新创建一个 "duplicate",例如 user_history,然后在各自的列中添加历史记录

Users: id, name, surname ...
Users_history: id, user_id, name, surname ... 
  1. 对这两种解决方案进行计时,您会发现哪一种更适合您。无法判断在您的应用程序和环境中哪个会更快。
  2. 这是一项设计决定,因此完全取决于您和您的要求。您需要考虑以下事项:

    • 如果用户更改了交易中的记录,则所有受影响的字段将由同一用户同时更改。使用您建议的结构,所有这些更改都需要一个单独的条目。

    • 使用您建议的结构,更难确定某条记录在给定时间点的样子,因为您基本上必须重播该记录插入后的所有更改。

    • 在专业方面,所有更改都存储在一个 table 中,即使您更改数据库架构,也不必更改日志记录的结​​构。

    • 您还必须考虑是要记录所有 table 的更改还是只记录部分选定的更改。

    • 如果正在记录的 table 引用其他 table,您还需要考虑如何记录。例如,如果你想记录交易,那么你可能有一个交易类型字段和一个单独的交易类型 table 列出详细描述,也许还有关于每个交易类型的其他信息。如果一个交易类型不再被使用,那么它可以从交易类型中移除table或者它的参数可能会改变。

鉴于此架构:

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 username/password 进行数据库访问并根据 MySQL 中的 users table 对您的用户进行身份验证,那么在执行任何操作之前删除,您需要在 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');