Tenemos una aplicación Java que utiliza MySQL, Hibernate (3.5.1-Final) y EHcache (1.2.3) para nuestro segundo nivel de caché.Hibernate caché de segundo nivel ObjectNotFoundException con un alto número de transacciones simultáneas
Nuestro nivel hibernate.properties aislamiento se ha comprometido Leer-isolation = 2
# 2-Read committed isolation
hibernate.connection.isolation=2
Bajo un elevado número de transacciones simultáneas, estamos viendo un problema por el que algunas colecciones (asociaciones DB) cuando está cargado lanzará una ObjectNotFoundException y parece que la memoria caché de segundo nivel está devolviendo una copia anterior de esa colección.
Tenemos muchos tipos diferentes de transacciones que acceden a esta colección (solo lectura) y solo una pareja que agregará/eliminará elementos de la misma.
No vemos este problema bajo carga de transacción única o incluso carga de transacción moderada (10 - 20 conexiones concurrentes).
Por ejemplo, tenemos una entidad Carácter:
@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;
Estamos manteniendo adecuadamente el gráfico de objetos cuando se eliminan las entidades retirándolos de la colección que están contenidas en Session.delete y llamar a().
character.getItems().remove(characterItem);
session.delete(characterItem);
Hemos intentado cambiar los elementos del Set; CacheConcurrencyStrategy de:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<CharacterItem> items;
Para
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<CharacterItem> items;
sin suerte.
No usamos bloqueos de bases de datos, sino que usamos optimistic concurrency control para atrapar y reintentar transacciones conflictivas.
El sólo 2 soluciones que podemos ver en este punto es:
intente coger el ObjectNotFoundException y tratar de desalojar a la colección inteligente (aunque no parece ser lo suficientemente contexto en el la excepción)
Usar la @NotFound(action=NotFoundAction.IGNORE) anotación en la colección de artículos, que ignorará y no tirar la ObjectNotFoundException (pero tenemos preocupaciones en cuanto a cómo funciona esto con el segundo nivel de Ca che y asegúrese de que está buscando los datos adecuados).
Me gustaría que hubiera una @NotFound (acción = NotFoundAction.EVICT_2ND_LEVEL_CACHE_RELOAD) donde sería desalojar a ese objeto de la caché e intentar recargar la colección.
También podríamos tratar de cambiar el FetchyType de LAZY a EAGER pero quiero tratar de entender el problema y elegir la mejor solución que proporcionará que los datos en nuestras transacciones sean consistentes bajo alta concurrencia.
¿Alguna vez resolvió esto correctamente? Tengo el mismo problema. – cherouvim