我目前正忙着为数据库中的某些表创建历史表。基本上我有主表和该表的副本,其中包含修改日期和操作列,用于存储执行的操作,例如更新,删除和插入。
到目前为止,我可以想到三个不同的地方,你可以做历史表工作。
我的主要问题是,在每个层中完成工作的优缺点和缺点是什么。
通过使用触发器方式,我能想到的一个优点是,无论在数据库上实施什么程序,都始终保持完整性。
答案 0 :(得分:12)
我这样说:
答案 1 :(得分:10)
触发器是实现简单历史记录的最快捷,最简单的方法。以下信息假设一个更复杂的示例,其中历史记录处理可能包含一些业务规则,并且可能需要在跟踪的表中找不到记录信息。
对于那些认为触发器比sprocs更安全的人,因为它们无法被绕过,我提醒他们他们做出以下假设:
!)存在阻止用户执行DISABLE TRIGGER的权限[但是权限可能也存在以限制对除了sprocs上的EXECUTE之外的所有数据库访问权限,这是企业应用程序的常见模式] - 因此必须承担正确的权限并且因此,在安全性和被绕过的能力方面,sprocs具有相同的触发因素
!)根据数据库,可以执行不触发触发器的更新语句。我可以利用嵌套触发器执行深度的知识来绕过触发器。唯一可靠的解决方案包括数据库中的安全性以及仅使用经批准的机制限制对数据的访问 - 无论是触发器,sprocs还是数据访问层。
我认为这里的选择很明确。如果多个应用程序正在访问数据,那么您希望从最低公共层控制历史记录,这将意味着数据库。
遵循上述逻辑,触发器或存储过程的选择还取决于存储过程是否是最低公共层。您应该优先选择sproc而不是触发器,因为您可以更好地控制性能和副作用,并且代码更易于维护。
触发器是可以接受的,但请尝试通过读取正在更新的表之外的数据来确保不增加锁定。限制触发器插入日志表,仅记录您需要的内容。
如果应用程序使用公共逻辑访问层,并且不太可能随着时间的推移而改变,我宁愿在此处实现逻辑。使用责任链模式和插件架构,从依赖注入驱动它,以允许在历史记录模块中进行各种处理,包括记录到完全不同类型的技术,不同的数据库,历史服务或您的任何其他内容可以想象。
答案 2 :(得分:6)
多年来一直使用基于触发器的方法,它确实对我们有效,但是你确实有以下几点要思考:
对使用频繁(例如,基于多租户SaaS的应用程序)的触发可能非常昂贵
在某些情况下,一些字段可能会变得多余。只有当你要记录的字段清晰时,触发才是好的;虽然使用一个应用程序,你可以有一个拦截器层,它可以帮助你根据“配置”记录某些字段;虽然它有自己的开销份额
如果没有足够的数据库控制,一个人可以轻松地禁用触发器,修改数据并启用触发器;所有这些都没有引发任何警报
对于Web应用程序,从池中建立连接,跟踪进行更改的实际用户可能会很乏味。一种可能的解决方案是在每个事务表中都有“EditedBy”字段。
答案 3 :(得分:5)
晚一个,但它增加了几个可以考虑的选项。
更改数据捕获: This功能在SQL Server 2008 R2 +中可用,但仅限于企业版。它允许您选择要跟踪的表,SQL Server将为您完成工作。它的工作原理是读取事务日志并用数据填充历史表。
读取事务日志:如果数据库处于完全恢复模式,则可以读取事务日志,并且可以找到有关几乎所有事务的详细信息。
缺点是默认情况下不支持此功能。选项是使用未记录的函数(如fn_dblog)或第三方工具(如ApexSQL Log)读取事务日志。
触发器:适用于没有太多触发器管理的少量表格。如果你想要审计很多表,那么你应该考虑一些第三方工具。
所有这些都在数据库级别工作,并且对应用程序完全透明。
答案 4 :(得分:2)
触发器是捕获更改的唯一可靠方法。如果您在存储过程或应用程序中执行此操作,您可以随时进入SQL并删除您没有日志的更改(无意中)。当然,不想留下日志的人可以禁用触发器。但是你宁愿强迫某人禁用日志记录而不是希望他们记得包含它。
答案 5 :(得分:0)
通常,如果选择应用程序层,则可以设计应用程序代码以在单个点进行日志记录,这将一致地处理所有历史表。不同的触发器是一种更复杂的维护方法,因为它们(根据数据库技术)为每个表复制:在数百个表的情况下,触发器的代码量是一个问题。
如果您的支持组织将维护您现在正在编写的代码,并且您不知道谁将维护您的代码(对于大型行业而言是典型的),您无法假设将要执行的人员的技能级别修复你的应用程序,在这种情况下,我认为最好使历史表工作原理尽可能简单,并且应用程序层可能是最适合此目的的地方。