Abbiamo un'applicazione Java che utilizza MySQL, Hibernate (3.5.1-Final) ed EHcache (1.2.3) per la nostra cache di secondo livello.Hibernate cache di secondo livello ObjectNotFoundException con un numero elevato di transazioni simultanee
Il nostro livello di isolamento è hibernate.properties Leggi-impegnata isolamento = 2
# 2-Read committed isolation
hibernate.connection.isolation=2
Sotto un elevato numero di transazioni concorrenti, stiamo vedendo un problema in cui alcune collezioni (associazioni DB) quando caricata lancerà un ObjectNotFoundException e sembra che la cache di secondo livello restituisca una vecchia copia di quella raccolta.
Abbiamo molti diversi tipi di transazioni che accedono a questa raccolta (solo lettura) e solo una coppia che aggiungerà/eliminerà elementi da essa.
Non vediamo questo problema sotto carico di una singola transazione o carico di transazione moderato (10 - 20 connessioni simultanee).
per esempio abbiamo un'entità Carattere:
@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;
Stiamo correttamente mantenendo il grafo di oggetti quando si eliminano le entità rimuovendoli dalla raccolta che stanno contenuti in e chiamando Session.delete().
character.getItems().remove(characterItem);
session.delete(characterItem);
Abbiamo provato a cambiare gli elementi impostati; CacheConcurrencyStrategy da:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<CharacterItem> items;
Per
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<CharacterItem> items;
senza fortuna.
Noi non utilizziamo blocchi di database invece usiamo optimistic concurrency control per intercettare e riprovare le transazioni in conflitto.
Il solo 2 soluzioni possiamo vedere, a questo punto è quello di:
tenta di catturare la ObjectNotFoundException e cercare di sfrattare in modo intelligente la raccolta (anche se non sembra essere abbastanza contesto in l'eccezione)
Utilizzare la @NotFound(action=NotFoundAction.IGNORE) annotazione sulla raccolta elementi, che ignorerà e non gettare l'ObjectNotFoundException (ma abbiamo preoccupazioni su come questo funziona con il 2 ° livello di ca che assicurano che stia guardando i dati corretti).
Vorrei che ci fosse un @NotFound (action = NotFoundAction.EVICT_2ND_LEVEL_CACHE_RELOAD) dove sarebbe sfrattare quell'oggetto dalla cache e tentare di ricaricare la collezione.
Si potrebbe anche provare a cambiare FetchyType da LAZY a EAGER ma voglio provare a capire il problema e scegliere la soluzione migliore che fornirà che i dati nelle nostre transazioni siano coerenti in alta concorrenza.
Hai mai risolto correttamente questo? Ho lo stesso problema. – cherouvim