PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Spring Data Pessimistic Lock Timeout mit Postgres

javax.persistence.lock.timeout funktioniert bei mir auch nicht, wenn es wie unten bereitgestellt wird

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

Aber dann habe ich etwas anderes ausprobiert, was funktioniert hat. Anstatt @Repository und CrudRepository zu verwenden, konfiguriere ich jetzt meinen Ruhezustand mit dem Entitätsmanager. Verwendet createQuery zusammen mit Sperre und Festlegen des Zeitlimits für die Sperre. Und diese Konfiguration funktioniert wie erwartet. Ich habe zwei Transaktionen, die parallel laufen und versuchen, genau dieselbe Zeile in DB zu sperren. Die erste Transaktion kann eine WRITE-Sperre erwerben und hält die Sperre etwa 10 Sekunden lang, bevor sie die Sperre freigibt. In der Zwischenzeit versucht die zweite Transaktion, eine Sperre für dieselbe Zeile zu erwerben, aber da javax.persistence.lock.timeout auf 15 Sekunden eingestellt ist, wartet sie auf die Freigabe der Sperre und erwirbt dann ihre eigene Sperre. Daher wird der Fluss serialisiert.

@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);
    }
}

Stellen Sie sicher, dass sich dieser Sperrmechanismus innerhalb einer Transaktion befindet, da die Sperre freigegeben wird, wenn eine Transaktion festgeschrieben oder zurückgesetzt wird.