Version de développement
Cette documentation décrit la version « next » (develop), non encore publiée. Pour la version stable, basculez sur « v5 » dans l'en-tête.
Développeurs

Verrous transactionnels dans PostgreSQL

Utiliser frappe.db.transaction_advisory_lock pour prendre un verrou advisory libéré à la fin de la transaction, sur PostgreSQL.

Verrous transactionnels dans PostgreSQL

frappe.db.transaction_advisory_lock prend un verrou advisory que PostgreSQL libère à la fin de la transaction en cours, au commit ou au rollback. Il n'y a pas de libération à écrire. Pour un verrou qui reste tenu après un commit, voir Verrous advisory.

frappe.db.transaction_advisory_lock(key, *, timeout=10)
ParamètreEffet
keyNom du verrou. Dodock le hache en un entier de 64 bits
timeoutAttente maximale en secondes. Après ce délai, Dodock lève frappe.QueryTimeoutError

Caractéristiques :

  • Dodock appelle pg_try_advisory_xact_lock toutes les 0,1 seconde, jusqu'au délai.
  • Un même processus peut reprendre le verrou dans la même transaction sans blocage.
  • PostgreSQL inclut ce verrou dans sa détection des interblocages, comme les verrous de ligne.

Sur MariaDB et SQLite, la méthode lève NotImplementedError. Testez le type de base avant l'appel.

Exemple

Exemple fictif : un contrôleur recalcule un compteur par article. Deux validations simultanées du même article doivent passer l'une après l'autre.

import frappe


def recalculer_compteur(item_code: str):
    if frappe.db.db_type == "postgres":
        frappe.db.transaction_advisory_lock(f"compteur:{item_code}")

    total = frappe.db.count("Stock Ledger Entry", {"item_code": item_code, "is_cancelled": 0})
    frappe.db.set_value("Item", item_code, "custom_nb_mouvements", total)
    # Le verrou est libéré au commit de la requête, ou au rollback en cas d'erreur.

custom_nb_mouvements est un champ personnalisé de l'exemple. N'appelez pas frappe.db.commit() dans un contrôleur : Dodock valide la transaction à la fin de la requête.

Voir les verrous actifs

SELECT locktype, objid, mode, granted
FROM pg_locks
WHERE locktype = 'advisory';