Spring 事务隔离级别
Spring Transaction Isolation Level
我们大多数人可能都在使用 Spring 和 Hibernate 进行数据访问。
我试图了解 Spring 事务管理器的一些内部结构。
根据Spring API,它支持不同的隔离级别 - doc
但是我找不到明确的信息,说明这些信息在哪些情况下真正有助于提高性能。
我知道 Spring Transaction
中的 readOnly
参数可以帮助我们使用不同的 TxManagers 来只读数据,并且可以利用良好的性能。但是它locks
table获取数据避免dirty-reads/non-committed读取-doc。
假设,在少数情况下,我们可能想盲目地将记录插入 table 并在不锁定 table 的情况下检索信息,这种情况我们从不更新 table 数据,我们只是插入和读取 [append-only]。我们可以使用更好的隔离来获得任何性能吗?
- 正如您从其中一个参考链接中看到的那样,我们真的需要 implement/write 我们自己的 CustomJPADiaelect 吗?
- 哪种隔离更符合我的要求?
实际上readOnly=true
不会引起对数据库的任何锁争用table,因为根本不需要锁定 - 数据库能够恢复到以前版本的记录而忽略所有新的记录变化。
如果 readOnly 为 true,您将在当前 Hibernate Session 中使用刷新模式 FlushMode.NEVER
以防止会话提交事务。另外,setReadOnly(true)
会在JDBCConnection上调用,也是提示底层数据库不要commit changes。
所以 readOnly=true
正是您正在寻找的(例如 SERIALIZED
隔离级别)。
Here 很好解释。
Read-only
允许某些优化,例如禁用脏检查,当您不打算更改实体时,您应该完全使用它。
每个 isolation level 定义数据库必须施加多少锁定以确保数据异常预防。
大多数数据库使用 MVCC (Oracle, PostgreSQL, MySQL) so readers don't lock writers and writers don't lock readers. Only writers lock writers as you can see in the following example。
REPEATABLE_READ
不必持有 锁 来防止并发事务修改当前事务加载的行。 MVCC 引擎允许其他事务读取行的已提交状态,即使您当前的事务已更改它但尚未提交(MVCC 使用撤消日志来恢复 pending changed
行的先前版本)。
在您的用例中,您应该使用 READ_COMMITTED
,因为它比其他更严格的隔离级别更好地扩展,并且您应该使用 optimistic locking 来防止在长时间对话中丢失更新。
更新
将 @Transactional(isolation = Isolation.SERIALIZABLE)
设置为 Spring bean 具有不同的行为,具体取决于当前事务类型:
- 对于
RESOURCE_LOCAL
个事务,JpaTransactionManager
可以为当前 运行 个事务应用特定的隔离级别。
- 对于 JTA 资源,事务范围的隔离级别不会传播到基础数据库连接,因为这是默认的 JTA 事务管理器行为。您可以按照
WebLogicJtaTransactionManager
. 的示例覆盖它
我们大多数人可能都在使用 Spring 和 Hibernate 进行数据访问。 我试图了解 Spring 事务管理器的一些内部结构。
根据Spring API,它支持不同的隔离级别 - doc 但是我找不到明确的信息,说明这些信息在哪些情况下真正有助于提高性能。
我知道 Spring Transaction
中的 readOnly
参数可以帮助我们使用不同的 TxManagers 来只读数据,并且可以利用良好的性能。但是它locks
table获取数据避免dirty-reads/non-committed读取-doc。
假设,在少数情况下,我们可能想盲目地将记录插入 table 并在不锁定 table 的情况下检索信息,这种情况我们从不更新 table 数据,我们只是插入和读取 [append-only]。我们可以使用更好的隔离来获得任何性能吗?
- 正如您从其中一个参考链接中看到的那样,我们真的需要 implement/write 我们自己的 CustomJPADiaelect 吗?
- 哪种隔离更符合我的要求?
实际上readOnly=true
不会引起对数据库的任何锁争用table,因为根本不需要锁定 - 数据库能够恢复到以前版本的记录而忽略所有新的记录变化。
如果 readOnly 为 true,您将在当前 Hibernate Session 中使用刷新模式 FlushMode.NEVER
以防止会话提交事务。另外,setReadOnly(true)
会在JDBCConnection上调用,也是提示底层数据库不要commit changes。
所以 readOnly=true
正是您正在寻找的(例如 SERIALIZED
隔离级别)。
Here 很好解释。
Read-only
允许某些优化,例如禁用脏检查,当您不打算更改实体时,您应该完全使用它。
每个 isolation level 定义数据库必须施加多少锁定以确保数据异常预防。
大多数数据库使用 MVCC (Oracle, PostgreSQL, MySQL) so readers don't lock writers and writers don't lock readers. Only writers lock writers as you can see in the following example。
REPEATABLE_READ
不必持有 锁 来防止并发事务修改当前事务加载的行。 MVCC 引擎允许其他事务读取行的已提交状态,即使您当前的事务已更改它但尚未提交(MVCC 使用撤消日志来恢复 pending changed
行的先前版本)。
在您的用例中,您应该使用 READ_COMMITTED
,因为它比其他更严格的隔离级别更好地扩展,并且您应该使用 optimistic locking 来防止在长时间对话中丢失更新。
更新
将 @Transactional(isolation = Isolation.SERIALIZABLE)
设置为 Spring bean 具有不同的行为,具体取决于当前事务类型:
- 对于
RESOURCE_LOCAL
个事务,JpaTransactionManager
可以为当前 运行 个事务应用特定的隔离级别。 - 对于 JTA 资源,事务范围的隔离级别不会传播到基础数据库连接,因为这是默认的 JTA 事务管理器行为。您可以按照
WebLogicJtaTransactionManager
. 的示例覆盖它