首页 > 解决方案 > Spring 应用程序中的 Hibernate Envers 性能和事务管理

问题描述

在我们的 SpringBoot 项目(使用 Spring MVC、Spring Data 等)中,我们使用 Hibernate Envers 来审计我们的数据库记录。有几件事我不确定。

1- 性能 - 线程:

假设我有一个被审计的 Person 实体。当我在相关表中插入/更新新的 Person 记录时,这会如何影响我的应用程序的性能?客户是否必须等待所有环境审计完成?Envers 会在单独的线程中处理这个问题吗?并且一旦插入成功,那么客户将能够继续他一直在做的任何任务吗?还是所有审计都在一个线程中处理,客户端应用程序必须等待所有审计记录完成?

2- 性能 - 缓存并执行:

Envers 是否缓存所有审计处理并在以后执行?我的意思是在所有录制完成之后。

3- 交易管理:

事务管理怎么样。假设我已成功为 Person 实体创建了一条记录,但在尝试创建审计记录时出错。那时会发生什么?这会回滚 Person 实体数据的记录吗?

4-分布式事务管理:

分布式事务环境怎么样?在分布式事务环境中如何确保 envers 审计记录的一致性?你有没有遇到过类似的情况,如果有的话,你是如何解决你的问题的?

您在使用 Envers 时遇到了哪些问题(如果有的话)。您应用了哪些替代审计方法?

请不要只提供链接并说“阅读此内容”。告诉我你知道什么以及你经历过什么。

非常感谢!

标签: hibernatehibernate-envers

解决方案


当我在相关表中插入/更新时,这对我的应用程序的性能有何影响?

Hibernate 有两种高级操作模式:有状态和无状态。

当 Hibernate 在有状态(例如Sessionnot StatelessSession)模式下运行时,它总是将实体操作收集到一个动作队列中。此操作队列稍后用于驱动事件系统,该系统不仅使 Hiberante 为这些操作执行 SQL,而且还通知集成商这些实体操作。

行动队列有许多目标。但是在性能方面,它允许 Hibernate 收集这些操作并延迟数据库操作,从而最大限度地减少连接获取和使用,从而可以批量执行数据库操作。

客户是否必须等待所有环境审计完成?
Envers 在单独的线程中处理这个?

是的,客户端将不得不等待,因为 Envers 与您的Session.

并且一旦插入成功,那么客户将能够继续他一直在做的任何任务吗?还是所有审计都在一个线程中处理,客户端应用程序必须等待所有审计记录完成?

Envers 维护了一个与 Hibernate 类似的操作队列。当 Hibernate 刷新其动作队列并触发事件时,Envers 将收到这些事件的通知,并将建立自己的动作队列。

Envers 的动作队列和 Hibernate 的主要区别在于,Envers 是一个提交时审计框架,它的动作队列不能手动刷新。审计操作队列将在事务提交前立即自动刷新,以保证所有来自 Hibernate 的事务操作都已首先发送到数据库。

所以是的,它都是单线程的。

Envers 是否缓存所有审计处理并在以后执行?我的意思是在所有录制完成之后。

是的,正如我上面描述的,但我将在这里说明。假设我们在客户端有一个打开的会话和一个正在使用的活动事务:

// User code calls save on some entity objects
// after these operations, some action queue entries are generated 
// No SQL has been executed
// No Audit operations have been executed or generated
session.save( someEntity1 );
session.save( someEntity2 );

// Lets say we manually flush Hibernate
// This flushes the Hibernate action queue
// SQL statements get fired for the above 2 saves
// Events are fired for integrators for the 2 save operations
// Envers generates AuditWorkUnit entries in its action queue for the operations
session.flush();

// User code calls save on another entity
// after these operations, some action queue entries are generated
// No SQL has been executed for this
// No Audit operations have been executed or generated
session.save( someEntity3 );

// commit the transaction
// This flueshes the Hibernate action queue
// sQL statements get fired for the above save of someEntity3
// Events are fired for integrators for the 1 save operation
// Envers generates AuditWorkUnit entries in its action queue for the operation
// pre-commit operations fire:
//   * Envers iterates its AuditWorkUnit action queue and executes those
//   * This generates Audit table SQL operations
// Transaction gets committed if no errors
session.getTransaction().commit();

事务管理怎么样。假设我已成功为 Person 实体创建了一条记录,但在尝试创建审计记录时出错。那时会发生什么?这会回滚 Person 实体数据的记录吗?

该事务将被标记为回滚;因此,审计模式中不会保存任何数据Person或审计等效项。

分布式事务环境怎么样?在分布式事务环境中如何确保 envers 审计记录的一致性?你有没有遇到过类似的情况,如果有的话,你是如何解决你的问题的?

那不适用;让我解释。

Envers itself is super simplistic. Those events I mentioned earlier result in a series of HQL statements being generated and handed to Hibernate for execution; nothing special there.

What that means is the same Session and Transaction you interacted with in your client's user code to send the operations to Hibernate is the same that Envers interacts with to do precisely the same.

So if that distributed transaction gets marked for rollback for whatever reason, not only is your Person data rolled back, so is the Envers operations themselves. Whether the transaction is distributed or not is irrelevant to the integration between Hibernate and Envers.


推荐阅读