PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Délai d'expiration du verrouillage pessimiste des données de printemps avec Postgres

javax.persistence.lock.timeout ne fonctionne pas pour moi non plus lorsqu'il est fourni comme ci-dessous

@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})

Mais ensuite j'ai essayé autre chose qui a fonctionné. Au lieu d'utiliser @Repository et d'utiliser CrudRepository, je configure maintenant mon hibernation à l'aide du gestionnaire d'entités. CreateQuery utilisé avec le verrouillage et la définition du délai d'expiration du verrouillage. Et cette configuration fonctionne comme prévu. J'ai deux transactions en parallèle et j'essaie de verrouiller exactement la même ligne dans la base de données. La première transaction est capable d'acquérir le verrou WRITE et maintient le verrou pendant environ 10 secondes avant de le libérer. Pendant ce temps, la deuxième transaction tente d'acquérir un verrou sur la même ligne, mais comme javax.persistence.lock.timeout est défini sur 15 secondes, il attend que le verrou soit libéré, puis acquiert son propre verrou. D'où la sérialisation du flux.

@Component
public class Repository {

    @PersistenceContext
    private EntityManager em;

    public Optional<Cache> getById(int id){
        List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
                            .setParameter(1, id)
                            .setHint("javax.persistence.lock.timeout", 15000)
                            .setLockMode(LockModeType.PESSIMISTIC_WRITE)
                            .getResultList();


        return Optional.ofNullable(list.get(0));
    }

    public void save(Cache cache) {
        cache = em.find(Cache.class, cache.getId());
        em.merge(cache);
    }
}

Assurez-vous que ce mécanisme de verrouillage se trouve à l'intérieur d'une transaction car le verrou sera libéré lorsqu'une transaction est validée ou annulée.