2010-06-24 6 views
7

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:

  1. tenta di catturare la ObjectNotFoundException e cercare di sfrattare in modo intelligente la raccolta (anche se non sembra essere abbastanza contesto in l'eccezione)

  2. 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.

+0

Hai mai risolto correttamente questo? Ho lo stesso problema. – cherouvim

risposta

1

Forse dovresti provare session.evict(characterItem) invece di session.delete?