[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