gpt4 book ai didi

java - 具有大量并发事务的 Hibernate 二级缓存 ObjectNotFoundException

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:36:44 26 4
gpt4 key购买 nike

我们有一个 Java 应用程序,它使用 MySQL、Hibernate (3.5.1-Final) 和 EHcache(1.2.3) 作为我们的二级缓存。

我们的 hibernate.properties 隔离级别是 Read-committed isolation = 2

# 2-Read committed isolation 
hibernate.connection.isolation=2

在大量并发事务下,我们发现某些集合(数据库关联)​​在加载时会抛出 ObjectNotFoundException 并且似乎二级缓存正在返回该集合的旧副本。

我们有许多不同类型的事务访问此集合(仅阅读),但只有几个会向其中添加/删除项目。

我们在单个事务负载甚至中等事务负载(10 - 20 个并发连接)下都没有发现此问题。

例如我们有一个 Character 实体:

@Entity
@Table(name = "CHARACTERS")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Character extends AbstractCharacter implements Serializable {
...
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@OneToMany(mappedBy = "character", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<CharacterItem> items;

在删除实体时,我们通过将它们从包含它们的集合中移除并调用 session.delete() 来正确维护对象图。

    character.getItems().remove(characterItem);
session.delete(characterItem);

我们已经尝试更改设置项; CacheConcurrencyStrategy 来自:

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<CharacterItem> items;

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<CharacterItem> items;

没有运气。

我们不使用数据库锁,而是使用 optimistic concurrency control捕获并重试冲突事务。

此时我们唯一能看到的 2 个解决方案是:

  1. try catch ObjectNotFoundException 并尝试智能地逐出集合(尽管异常中似乎没有足够的上下文)

  2. 使用 @NotFound(action=NotFoundAction.IGNORE) items 集合上的注释,它将忽略并且不会抛出 ObjectNotFoundException(但我们担心它如何与二级缓存一起工作并确保它正在查看正确的数据)。

我希望有一个 @NotFound(action=NotFoundAction.EVICT_2ND_LEVEL_CACHE_RELOAD) 可以从缓存中逐出该对象并尝试重新加载集合。

我们也可以尝试将 FetchyType 从 LAZY 更改为 EAGER,但我想尝试理解问题并选择最佳解决方案,以保证我们事务中的数据在高并发情况下保持一致。

最佳答案

也许您应该尝试使用 session.evict(characterItem) 而不是 session.delete

关于java - 具有大量并发事务的 Hibernate 二级缓存 ObjectNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3113202/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com