Forse un po' brutale come soluzione, ma se potessi impostare a livello di
connessione a postgresql (da come capisco nella web api in c# che accede)
transaction isolation a serializable, potrebbe essere una possibile soluzione
________________________________
Da: postgresql-it-bounce@xxxxxxxxxxxxx <postgresql-it-bounce@xxxxxxxxxxxxx> per
conto di Riccardo Penco <riccardo.penco@xxxxxxxxx>
Inviato: giovedì 9 settembre 2021 12:01
A: postgresql-it@xxxxxxxxxxxxx <postgresql-it@xxxxxxxxxxxxx>
Oggetto: [postgresql-it] Re: Problema con trigger e funzioni simultanee
Il giorno gio 9 set 2021 alle ore 08:15 Luca Ferrari
<fluca1978@xxxxxxxxx<mailto:fluca1978@xxxxxxxxx>> ha scritto:
Da quello che posso capire potresti provare a usare degli advisory
lock
<https://www.postgresql.org/docs/12/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS>
dentro alla tua funzione.
Altrimenti, penso che un CHECK o EXCLUDE sulla tabella possa riuscire
a fare quello che fa il tuo trigger, ma effettivamente servirebbero
maggiori dettagli su tutta la logica.
in pratica ho usato questa fsm
(https://raphael.medaer.me/2019/06/12/pgfsm.html) per definire gli stati e le
transizioni possibili di una certa entità.
Ho aggiunto una funzione di inserimento 'massivo' di un evento per un array di
id di queste entità: la funzione riceve un array di interi con gli id di tutte
le entità (che sono nello stato 'X') e un evento ('fromXtoY') per portare
massivamente tutte queste entità nello stato 'Y'. A seconda del numero di id
passati, questa funzione può impiegare anche una decina di secondi per
completarsi.
Da front end (applicazione javascript che si appoggia ad una Web API .net core
in C# sullo stesso server CentOS) posso richiamare più volte il WS che
inserisce massivamente gli eventi (il bottone non viene disabilitato al primo
click...).
Il risultato è che gli eventi vengono inseriti 2 o più volte e quindi per tutte
le entità coinvolte la FSM è corrotta (non posso inserire l'evento 'fromXtoY'
per un'entità già nello stato 'Y').
Mi sarei aspettato che le chiamate successive alla prima della funzione di
inserimento massivo fallissero...
Io penso che il "buco" sia nel tuo trigger: probabilmente tu ti
aspetti che il trigger possa fare piu' controlli di quelli che può
effettivamente fare, quindi immagino che ti manchino dei vincoli sulla
tabella se la concorrenza ti provoca problemi.
Credo anche io che il buco sia nel trigger, il problema è che sono riuscito a
riprodurlo solo dal frontend, vari tentativi di ottenere gli stessi problemi in
pgadmin4 o programmi simili sono sempre falliti.
Ho anche pensato alla possibilità che .net core possa riciclare la stessa
connessione in thread diversi, cosa non possibile come indicato dalla
documentazione (https://www.postgresql.org/docs/12/libpq-threading.html)
One thread restriction is that no two threads attempt to manipulate the same
PGconn object at the same time. In particular, you cannot issue concurrent
commands from different threads through the same connection object. (If you
need to run concurrent commands, use multiple connections.)
Ma sinceramente credo il problema sia più facilmente nel trigger...
Luca
ciao
riki