历史表的优点、缺点和陷阱 - 使用触发器、存储过程或在应用程序级别 [关闭]

Posted

技术标签:

【中文标题】历史表的优点、缺点和陷阱 - 使用触发器、存储过程或在应用程序级别 [关闭]【英文标题】:History tables pros, cons and gotchas - using triggers, sproc or at application level [closed] 【发布时间】:2010-11-18 00:59:54 【问题描述】:

我目前正在考虑在我的数据库中为我的一些表创建历史表的想法。基本上我有主表和该表的副本,其中包含修改日期和操作列来存储执行的操作,例如更新、删除和插入。

到目前为止,我可以想到三个不同的地方可以做历史表格工作。

在主表上触发更新、插入和删除。 (数据库) 存储过程。 (数据库) 应用层。 (应用)

我的主要问题是;在每一层做这项工作的优缺点是什么?

使用触发器方式我能想到的一个优点是,无论在数据库之上实现什么,都始终保持完整性。

【问题讨论】:

【参考方案1】:

我会这样说:

存储过程:如果您直接修改表,它们会被绕过。数据库上的安全性可以控制这一点 应用:同样的交易。此外,如果您有多个应用程序,可能使用不同的语言,则需要在每个堆栈中实现它,这有点多余;和 触发器:对应用程序透明,并将捕获所有更改。这是我的首选方法。

【讨论】:

我的想法也是,通过使用触发器,它还会从应用程序中删除所有审计逻辑,从而消除我错过调用正确方法的机会。【参考方案2】:

触发器是实现简单历史记录的最快捷、最简单的方法。以下信息假设了一个更复杂的示例,其中历史处理可能包括一些业务规则,并且可能需要在被跟踪的表中找不到的日志记录信息。

对于那些认为触发器比存储过程更安全的人,因为它们无法被绕过,我提醒他们他们正在做出以下假设:

!) 存在阻止用户执行 DISABLE TRIGGER 的权限 [但也可能存在权限以限制对数据库的所有访问,除了 EXECUTE on sprocs 这是企业应用程序的一种常见模式] - 因此必须假设正确的权限和因此,就安全性和被绕过的能力而言,sprocs 的触发器相同

!) 根据数据库,可能会执行不触发触发器的更新语句。我可以利用嵌套触发器执行深度的知识来绕过触发器。唯一确定的解决方案包括数据库的安全性和仅使用经批准的机制限制对数据的访问——无论这些机制是触发器、存储过程还是数据访问层。

我认为这里的选择很明确。如果多个应用程序正在访问数据,那么您希望从最低的公共层控制历史记录,这将意味着数据库。

按照上面的逻辑,触发器还是存储过程的选择又取决于存储过程是否是最底层的公共层。您应该更喜欢存储过程而不是触发器,因为您可以更好地控制性能和副作用,并且代码更易于维护。

触发器是可以接受的,但请尽量确保不会通过读取正在更新的表之外的数据来增加锁。将触发器限制为插入到日志表中,仅记录您需要的内容。

如果应用程序使用一个通用的逻辑访问层并且这不太可能随着时间的推移而改变,我更愿意在这里实现逻辑。使用责任链模式和插件架构,从依赖注入驱动它,以允许在你的历史模块中进行各种处理,包括记录到完全不同类型的技术、不同的数据库、历史服务或任何其他你可以想象。

【讨论】:

【参考方案3】:

多年来一直使用基于触发器的方法,它对我们来说确实效果很好,但是您确实需要考虑以下几点:

    在大量使用(例如,基于多租户 SaaS 的应用程序)上的触发器可能非常昂贵

    在某些情况下,一些字段可能会变得多余。只有当您对要记录的字段非常清楚时,触发器才是好的;尽管使用应用程序,您可以有一个拦截器层,它可以帮助您根据“配置”记录某些字段;尽管有自己的间接费用份额

    如果没有足够的数据库控制,人们可以轻松地禁用触发器、修改数据和启用触发器;一切都没有引起任何警报

    在 Web 应用程序的情况下,连接是从池中建立的,跟踪进行更改的实际用户可能很乏味。一种可能的解决方案是在每个事务表中都有“EditedBy”字段。

【讨论】:

【参考方案4】:

较晚的一个,但它增加了几个可以考虑的选项。

更改数据捕获: This 功能在 SQL Server 2008 R2+ 中可用,但仅在企业版中可用。它允许您选择要跟踪的表,SQL Server 将为您完成这项工作。它通过读取事务日志和用数据填充历史表来工作。

读取事务日志:如果数据库处于完全恢复模式,则可以读取事务日志,并且可以找到几乎所有事务的详细信息。

缺点是默认情况下不支持。选项是使用 fn_dblog 等未记录的函数或ApexSQL Log 等第三方工具来读取事务日志。

触发器:适用于没有太多触发器需要管理的少量表。如果您有很多表要审核,那么您应该考虑使用一些第三方工具。

所有这些都在数据库级别工作,并且对应用程序完全透明。

【讨论】:

【参考方案5】:

触发器是捕获更改的唯一可靠方法。如果您在 Stored Procs 或应用程序中执行此操作,您可以随时进入并使用 SQL 删除您没有记录的更改(无意中)。当然,不想留下日志的人可以禁用触发器。但你宁愿强迫某人禁用日志记录,也不愿希望他们记得包含它。

【讨论】:

【参考方案6】:

通常,如果您选择应用程序层,您可以设计您的应用程序代码以单点进行日志记录,这将一致地处理您的所有历史表。不同的触发器是一种更复杂的维护方法,因为它们(取决于数据库技术)为每个表复制:如果有数百个表,触发器的代码量可能是个问题。

如果您有一个支持组织来维护您现在正在编写的代码,并且您不知道谁将维护您的代码(对于大型行业来说很典型),您无法假设谁将维护您的代码水平修复你的应用程序,在这种情况下,我认为最好使历史表的工作原理尽可能简单,而应用程序层可能是实现此目的的最佳位置。

【讨论】:

以上是关于历史表的优点、缺点和陷阱 - 使用触发器、存储过程或在应用程序级别 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

链表都有哪些优点和缺点?

MySQL触发器定义及其优缺点

数据库基础详解:存储过程、视图、游标、SQL语句优化以及索引

存储过程跟SQL语句比较,各有啥优点和缺点?

数仓设计--维度(全量、拉链表)

mysql内部代码的优缺点