[Python] psycopg, cursori e connessioni: tenere occupato un id

Marco Fochesato marcofoc a libero.it
Lun 16 Maggio 2011 22:03:47 CEST


Il giorno lun, 16/05/2011 alle 21.52 +0200, Daniele Varrazzo ha scritto:
> On Mon, 16 May 2011 19:37:21 +0200, Marco Fochesato <marcofoc a libero.it>
> wrote:
> 
> > No, niente buchi.
> > Allora, spieghiamoci così:
> > siamo di fronte ad un gestionale.
> 
> come sempre :)
> 
> > L'utente x parte per compilare un DDT.
> 
> Problemi con le zanzare?
> 
> > L'applicazione "prenota" un id (chiave primaria) per il documento.
> > L'utente y parte anche lui per compilare un DDT.
> > L'applicazione "prenota" anche per lui un id, lo stesso di quello sopra
> > (visto che non è ancora stato chiuso, e potrebbe anche darsi che x
> > decida di non chiuderlo e annullare tutto.. (qui è il nocciolo)).
> > Il primo che finisce e chiude il ddt, si prende il numero (commit).
> > Per il secondo, verrà sollevata una eccezzione e verrà concesso un altro
> > id (non mi interessa qui stabilire come).
> 
> Non mi sembra il migliore dei comportamenti: perché far fallire la seconda
> transazione quando ci sono almeno diversi modi di farla riuscire?
> 
> E se il secondo finisce prima del primo? Dovrebbe fallire il primo?
> 
> > Quello che mi interessa è la "prenotazione".
> 
> Se vuoi davvero prenotare un record, puoi inserire un record incompleto
> oppure tenere una tabella separata delle prenotazioni. Forse anche gli
> advisory lock possono essere utili.
> 
> > Io ho bisogno, durante la compilazione del documento, di testare degli
> > inserimenti, e vorrei che l'applicazione ragionasse come se l'id fosse
> > inserito. Ma se arriva y, che l'id fosse disponibile anche per lui.
> 
> Per fare quello che vuoi tu ha ragione Manlio: usare qualcosa tipo max(id)
> + 1 è la soluzione migliore. Manlio però si è dimenticato di dire di
> prendere un lock sulla tabella (in pratica gli inserimenti devono essere
> serializzati):
> 
> 1) quando il documento viene prenotato:
> 
>    a) prendi un lock sulla tabella che conflitti con se stesso, per
> esempio "LOCK TABLE blah IN EXCLUSIVE MODE".
>    b) usa come prossimo id "SELECT max(id) FROM blah"
>    c) commit sulla connessione, in modo da liberare il lock.
> 
> 2) quando il documento viene salvato:
> 
>    a) prendi lo stesso lock sulla stessa tabella
>    b) prendi lo stesso max
>    c) se il max è diverso da quanto registrato, tira un eccezione.
> 
> O alternativamente scrivi direttamente il max nel database e aspettati
> un'eccezione se c'è una constraint UNIQUE su quel campo.
> 
> Questa è un'implementazione pessima di un lock pessimistico: se uno
> comincia un'operazione, qualunque operazione concorrente è destinata a
> fallire: perché tu voglia fare questo onestamente mi sfugge.
> 
> La documentazione sui lock
> (http://www.postgresql.org/docs/9.1/static/explicit-locking.html) e sul
> comando LOCK (http://www.postgresql.org/docs/9.1/static/sql-lock.html) può
> esserti utile.
> 
> Lasciare aperta la transazione per tutta la durata dell'edit è qualcosa da
> NON fare.
> 
> 
Ottimo Daniele!
Sei stato molto chiaro.
Lock table, serializzazioni.
Tutte cose che non conosco...
Come credo dica il mitico Rocco: l'affare s'ingrossa!!!

Grazie delle dritte ragazzi!
Marco




Maggiori informazioni sulla lista Python