每个表上有一个日志表与日志列

时间:2009-09-23 12:50:43

标签: database database-design

我将插入和更新信息记录到每个表

create_date    TIMESTAMP
create_user_id INT
update_date    TIMESTAMP
update_user_id INT

我认为不是将它们放在每个表上,而是只创建一个日志表并在每个表上引用日志表,这样我只能在需要时检索日志信息。我知道这取决于应用程序(我正在开发一个像应用程序这样的小型商业ERP),但你有这种类型的表的经验吗?任何性能,维护问题?你喜欢哪个?感谢。

log_id         LONG
create_date    TIMESTAMP
create_user_id INT
update_date    TIMESTAMP
update_user_id INT

编辑:我总结了一个解决方案,在每个表上只使用update_date(insert将被视为更新,没有数据删除但只是停用)和update_user_id列。我使用MySQL,在生产环境中会有主服务器和从服务器。如果任何情况发生回溯数据,我将使用从服务器上的复制日志来审计数据更改,因此设计更简单,尽管不容易进行审计。

4 个答案:

答案 0 :(得分:5)

如果写入除了正在进行的任何其他写入之外,单个日志表很容易成为瓶颈。

您也会为某些查询生成额外的JOIN。

在我看来,我没有看到单独表的好处,除了使其余的DB表有点'更清洁'

答案 1 :(得分:3)

单个日志是一件很棒的事情。

在每个表上,都有一个ID列,仅用于记录目的。称之为LOG_ID或其他东西。

任何时候你执行INSERT,UPDATE或DELETE都会像这样工作。

  1. 插入日志条目,获取已分配的LOG_ID。

  2. 执行INSERT或UPDATE操作,在更改的行上设置LOG_ID外键。对于DELETE,您有两种选择:实际删除行或将该行标记为“非活动”但不实际删除它。第二个选择使您所有更改的日志完全完整,但由于必须跳过非活动行,因此会使您的表非常大且速度慢。

  3. 提交。

  4. 确保您的日志设计可以包含以下类型的信息。

    1. 数据库行更改(插入,更新,删除)。 Insert和Update更改将在某处对已更改的行进行FK引用。请确保包含表名,以便应用程序可以正确找到表。删除更改只会有一个表名。

    2. 批量作业运行等其他处理信息。这样,您可以记录批处理作业的启动/停止和运行时间,并保留完整的处理历史记录。

答案 2 :(得分:1)

大约20年前,我了解到处理这类信息的最佳方法是插入数据库。您不应修改现有记录,绝对不能删除任何记录。基本上,您要存储的不是数据本身,而是数据的修改。因此,如果只有足够的CPU /磁盘速度来遍历所有数据来计算基于这些插入的数据,那么您最终会得到一个可以执行所需操作的单个表。

只需存储修改,您就可以保留所有数据的完整历史记录,从而使您非常灵活。基本上,你只需要一个包含所有内容的表。缺点是你需要做更多的计算并需要更多的磁盘读取,所以你需要一些技巧来加快这个过程。以性能为代价的灵活性......

在这种情况下,您最终会遇到类似的问题。任何需要添加或更新记录的内容都可以访问单个表。这将是你的瓶颈。它在单用户环境中仍然很棒,因为只有一个用户会使用它。在低用户环境中,它仍然可以具有非常好的性能。但如果您有250多个用户一直访问此表,则会降低整体性能。

另外,当有人删除记录时,您会引入维护问题。在这些情况下,还需要删除此日志表中的记录。

让我回想起我刚开始提到的事情......你能做的就是将历史表和常规表结合起来。无论何时插入,修改或删除记录,都应在此修改表中添加记录,包括时间戳和用户引用。这将保留数据的历史记录,通常,您只需要在此表中插入。这应该还很快。另外,您可以通过重播此修改表中的所有操作来重新创建数据库的全部内容,以防万一。

插入可以合理快速,因此性能损失很小,但这取决于您的实现。

但无论出于何种原因,在学习使用修改表后,我从未遇到过可以使用这种技术的实际情况。

答案 3 :(得分:1)

我们通常在大多数表格中使用这些:

LastChgID      int
LastChgDate    datetime

有时会使用,这只有几个:

CreateID       int
CreateDate     datetime
LastChgID      int
LastChgDate    datetime

在其他人身上有一个完整的镜像表,我们使用更改类型标志,日期时间和用户ID记录每一列。

我会远离你一直更新的表,只需添加数据库所用的列来存储信息。我们每次调用一个存储过程时都会增加一个表(带有更新),这是一个死锁磁铁。

我们有一个通用的日志表,但它只是插入,包含调试和错误信息。每次更改任何行时都不会更新它,只有当开发人员决定在那里写东西时,才会使用包含该消息的长格式化字符串来处理一些标题字段(标识,日期时间,用户ID,调用过程)。