您如何看待这种在mysql中记录更改并具有某种审计跟踪的方法

flo*_*len 12 php mysql database audit-trail

我现在已经阅读了几个主题并做了一些关于将更改记录到mysql表的研究.首先让我解释一下我的情况:

我有一张带桌子的票务系统:'票'

截至目前,我已经创建了触发器,它将在我的表中输入一个重复的条目:'ticket_history',其中"action" "user""timestamp"作为附加列.经过几周的测试和测试后,我对这个版本感到不满,因为每次更改都会在历史记录表中创建我的行的完整副本.我确实知道磁盘空间很便宜,我不应该担心它,但是为了找回用户的某种日志或漂亮的历史是痛苦的,至少对我来说是这样.还有我写过的触发器,即使没有变化,我也会在历史记录中获得新的一行.但这只是我触发器的设计缺陷!

这是我的触发器:

BEFORE UPDATE ON ticket FOR EACH ROW
BEGIN
INSERT INTO ticket_history
SET
    idticket = NEW.idticket,
    time_arrival = NEW.time_arrival,
    idticket_status = NEW.idticket_status,
    tmp_user = NEW.tmp_user,
    action = 'update',
    timestamp = NOW();
END
Run Code Online (Sandbox Code Playgroud)

我的新方法是为了避免触发器

在花了一些时间讨论这个话题之后,我想出了一个我想讨论和实现的方法.但首先我会对此有一些疑问:

我的想法是创建一个新表:

    id   sql_fwd        sql_bwd      keys      values    user       timestamp
    -------------------------------------------------------------------------
    1    UPDATE...      UPDATE...    status    5         14          12345678
    2    UPDATE...      UPDATE...    status    4         7           12345678
Run Code Online (Sandbox Code Playgroud)

在我看来,流程看起来像这样:

首先,我会从数据库中选择一些或更多内容:

SELECT keys FROM ticket;

然后我在2个输入字段中显示数据:

<input name="key" value="value" /> <input type="hidden" name="key" value="value" />

点击提交并将其提供给我的功能:

我将再次从SELECT开始:SELECT * FROM ticket; 并确保隐藏的输入字段==最新选择的值.如果是这样,我可以继续并知道没有其他用户同时改变了某些东西.如果隐藏字段不匹配,我将用户带回表单并显示一条消息.

接下来,我将构建操作的SQL查询以及撤消这些更改的查询.

$sql_fwd = "UPDATE ticket 
            SET idticket_status = 1
            WHERE idticket = '".$c_get['id']."';";

$sql_bwd = "UPDATE ticket 
            SET idticket_status = 0
            WHERE idticket = '".$c_get['id']."';";
Run Code Online (Sandbox Code Playgroud)

我在票证上运行UPDATE 并在我的新表中插入一个新条目以进行日志记录.

有了这个,我可以尝试捕获可能的覆盖,而两个用户在同一时间编辑同一张票,而对于我的历史记录,我可以简单地查找键和值并生成某种列表.还有SQL_BWD我只能撤消更改.

我的问题是:

  • 每次我想要更新某些内容时,是否会注意到另外选择?
  • 我是否会因触发器而失去一些好处?
  • 有什么大的缺点吗?
  • 我的mysql服务器或php上有没有这样的功能?
  • 或者可能有更简单的方法来做这样的事情
  • 可能是我的触发器略有变化我已经足够了吗?
  • 如果我理解这一点,那么只有在值发生变化但是执行触发器时,MySQL才会执行更新吗?
  • 如果我能够更改触发器,我仍然可以防止以某种方式覆盖数据,而2个用户尝试在mysql服务器上同时编辑票证,或者我是否仍然使用PHP执行此操作?

谢谢你的帮助

Nev*_*uyt 2

我之前回答过类似的问题。您会在该问题中看到一些不错的选择。

就您而言,我认为您正在合并几个问题 - 一个是“存储审计跟踪”,另一个是“管理许多客户端可能想要更新单行的情况”。

首先,我不喜欢触发器。它们是其他一些操作的副作用,对于重要的情况,它们使调试变得更加困难。设计不当的触发器或审计表确实会减慢您的应用程序的速度,您必须确保您的触发器逻辑在许多开发人员之间协调。我意识到这是个人偏好和偏见。

其次,根据我的经验,要求很少是“随着时间的推移显示这个表的状态” - 它几乎总是“让我看看系统随着时间的推移发生了什么”,如果该要求存在,通常是相当公平的高优先级。例如,对于票务系统,您可能需要创建和更改票证状态的用户的姓名和电子邮件地址;类别/分类的名称,也许是项目的名称等。所有这些属性都可能是其他表的外键。当确实发生需要审计的事情时,要求可能是“让我立即查看”,而不是“让数据库开发人员花几个小时尝试从 8 个不同的历史表中拼凑出图片。在票务系统中,这可能是一个要求以便票证详细信息屏幕显示这一点。

如果这一切都是真的,那么我认为由触发器填充的历史表不是一个好主意 - 您必须将所有业务逻辑构建到两组代码中,一组用于显示“常规”应用程序,一组用于显示“审计追踪”。

相反,您可能希望将“时间”构建到您的数据模型中(这是我对另一个问题的回答的要点)。

从那时起,一种新的数据架构风格出现了,称为CQRS。这需要一种非常不同的方式来看待应用程序设计,但它是明确为反应式应用程序设计的;这些提供了更好的方法来处理“如果当前用户正在填写表单时有人编辑记录会发生什么”问题。Stack Overflow 就是一个例子 - 我们可以在输入评论或答案时看到问题是否已更新,或者是否发布了其他答案或评论。有一个PHP 反应式库