gpt4 book ai didi

mysql - 数据变更历史与审计表 : Grouping changes

转载 作者:可可西里 更新时间:2023-11-01 06:37:35 25 4
gpt4 key购买 nike

假设我想将用户和组存储在 MySQL 数据库中。他们有一个关系 n:m。为了跟踪所有更改,每个表都有一个审计表 user_journal、group_journal 和 user_group_journal。 MySQL 触发器在每次 INSERT 或 UPDATE 时将当前记录复制到日志表(不支持 DELETES,因为我需要应用程序用户删除记录的信息——所以有一个标记 active将被设置为 0 而不是删除)。

我的问题是:假设我一次将 10 个用户添加到一个组中。当我稍后在应用程序的用户界面中单击该组的历史记录时,我希望将这 10 个用户的添加视为一步,而不是 10 个独立的步骤。 是否有一个很好的解决方案来将这些更改组合在一起?也许可以有一个计数器,每次触发器被...触发时都会递增?我从未使用过触发器。

最好的解决方案是将在事务中所做的所有更改放在一起。因此,当用户一步更新组名并添加 10 个用户(一次表单 Controller 调用)时,这将是历史记录中的一步。也许可以定义一个随机散列或在每次事务开始时递增一个全局计数器并在触发器中访问该值?

我不想让表设计比为每个“真实”表设计一个日志表更复杂。我不想在每个数据库表中添加事务哈希(意思是“真实”表,而不是审计表——当然可以)。此外,我希望在数据库中有一个解决方案——而不是在应用程序中。

最佳答案

我试了一下,现在我找到了一个很好的解决方案:

数据库设置

# First of all I create the database and the basic table:

DROP DATABASE `mytest`;
CREATE DATABASE `mytest`;
USE `mytest`;
CREATE TABLE `test` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`something` VARCHAR(255) NOT NULL
);

# Then I add an audit table to the database:

CREATE TABLE `audit_trail_test` (
`_id` INT PRIMARY KEY AUTO_INCREMENT,
`_revision_id` VARCHAR(255) NOT NULL,
`id` INT NOT NULL,
`something` VARCHAR(255) NOT NULL
);

# I added a field _revision_id to it. This is
# the ID that groups together all changes a
# user made within a request of that web
# application (written in PHP). So we need a
# third table to store the time and the user
# that made the changes of that revision:

CREATE TABLE `audit_trail_revisions` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`user_id` INT NOT NULL,
`time` DATETIME NOT NULL
);

# Now we need a procedure that creates a
# record in the revisions table each time an
# insert or update trigger will be called.

DELIMITER $$

CREATE PROCEDURE create_revision_record()
BEGIN
IF @revision_id IS NULL THEN
INSERT INTO `audit_trail_revisions`
(user_id, `time`)
VALUES
(@user_id, @time);
SET @revision_id = LAST_INSERT_ID();
END IF;
END;

# It checks if a user defined variable
# @revision_id is set and if not it creates
# the row and stores the generated ID (auto
# increment) into that variable.
#
# Next I wrote the two triggers:

CREATE TRIGGER `test_insert` AFTER INSERT ON `test`
FOR EACH ROW BEGIN
CALL create_revision_record();
INSERT INTO `audit_trail_test`
(
id,
something,
_revision_id
)
VALUES
(
NEW.id,
NEW.something,
@revision_id
);
END;
$$

CREATE TRIGGER `test_update` AFTER UPDATE ON `test`
FOR EACH ROW BEGIN
CALL create_revision_record();
INSERT INTO `audit_trail_test`
(
id,
something,
_revision_id
)
VALUES
(
NEW.id,
NEW.something,
@revision_id
);
END;
$$

应用程序代码(PHP)

$iUserId = 42;

$Database = new \mysqli('localhost', 'root', 'root', 'mytest');

if (!$Database->query('SET @user_id = ' . $iUserId . ', @time = NOW()'))
die($Database->error);
if (!$Database->query('INSERT INTO `test` VALUES (NULL, "foo")'))
die($Database->error);
if (!$Database->query('UPDATE `test` SET `something` = "bar"'))
die($Database->error);

// To simulate a second request we close the connection,
// sleep 2 seconds and create a second connection.
$Database->close();
sleep(2);
$Database = new \mysqli('localhost', 'root', 'root', 'mytest');

if (!$Database->query('SET @user_id = ' . $iUserId . ', @time = NOW()'))
die($Database->error);
if (!$Database->query('UPDATE `test` SET `something` = "baz"'))
die($Database->error);

然后……结果

mysql> select * from test;
+----+-----------+
| id | something |
+----+-----------+
| 1 | baz |
+----+-----------+
1 row in set (0.00 sec)

mysql> select * from audit_trail_test;
+-----+--------------+----+-----------+
| _id | _revision_id | id | something |
+-----+--------------+----+-----------+
| 1 | 1 | 1 | foo |
| 2 | 1 | 1 | bar |
| 3 | 2 | 1 | baz |
+-----+--------------+----+-----------+
3 rows in set (0.00 sec)

mysql> select * from audit_trail_revisions;
+----+---------+---------------------+
| id | user_id | time |
+----+---------+---------------------+
| 1 | 42 | 2013-02-03 17:13:20 |
| 2 | 42 | 2013-02-03 17:13:22 |
+----+---------+---------------------+
2 rows in set (0.00 sec)

如果我遗漏了一点,请告诉我。我将不得不向审计表中添加一个 action 列,以便能够记录删除。

关于mysql - 数据变更历史与审计表 : Grouping changes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14112314/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com