2010-08-17 12 views
5

Alla ricerca di una consulenza pratica:Select-locking in Rails con MySQL

Supponiamo di avere un oggetto Account con attributo limite. Ogni giorno ci possono essere n pagamenti, con somma dei loro importi fino al limite del conto. Quando crea un nuovo pagamento, controlla se il suo importo + gli importi degli altri pagamenti del giorno sono ancora entro il limite dell'account e salva il record o visualizza l'errore.

Ora, supponiamo di avere un account con limite 100 $, e contemporaneamente vengono creati due pagamenti di 99 $. Ciascuno farebbe una selezione, vedrà che non c'è nulla e procederà a salvarsi, con il risultato di salvare 198 $ totali.

Cosa faresti? Stavo pensando di emettere un blocco di scrittura sulla tabella dei pagamenti all'inizio della transazione, ma sembra abbastanza pesante, visto che mi interessa solo non permettere che i pagamenti appartenenti a un account specifico non vengano letti da altre transazioni. Ci sono altre opzioni, modi migliori per gestire questa situazione?

risposta

3

Stavo pensando di emissione di un blocco di scrittura sul tavolo pagamenti all'inizio della transazione, ma che sembra quit eheavy mano

Supponendo che tu stia già parlando di transazioni, presumo che tu non stia usando MyISAM, ma invece InnoDB o qualche altro motore che supporta già le transazioni.

Il blocco per operazioni di lettura o scrittura sulle transazioni per preservare l'atomicità delle operazioni non è un'operazione da eseguire manualmente. Per fare ciò è il lavoro del livello di isolamento della transazione. Ciò manterrà anche l'atomicità delle operazioni tra l'apertura della transazione e il blocco della tabella o dei record, in modo che nessuna lettura passi nel frattempo.

Per il caso d'uso che si descrive, si intendono le transazioni con il livello di isolamento 'SERIALIZABLE', che bloccherà per la lettura e la scrittura. Inoltre, bloccherà automaticamente solo i record da cui hai letto (anche se chiedi intervalli), lasciando quindi liberi i record restanti per la manipolazione.

Attraverso il livello di isolamento "SERIALIZABLE", nel momento in cui si leggono le informazioni dalla tabella, qualsiasi tentativo di aggiornare o leggere tali record dovrà attendere fino al termine della transazione. Inoltre, assicurati di leggere prima di eseguire l'aggiornamento sulla stessa transazione in modo da essere sicuro di lavorare con il valore corretto.

Si può leggere di più su livelli di isolamento qui: http://en.wikipedia.org/wiki/Isolation_(database_systems) http://www.databasejournal.com/features/mysql/article.php/3393161/MySQL-Transactions-Part-II---Transaction-Isolation-Levels.htm

si può imparare come impostare il livello di isolamento delle transazioni qui: http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html

+0

"il momento di leggere le informazioni dalla tabella , qualsiasi tentativo di aggiornare o leggere quei record dovrà attendere fino a quella transazione "- cosa succede se la selezione non produce record? o nel caso del richiedente-domanda, sta interrogando per il valore aggregato dei record esistenti prima di aggiungerne di nuovi. come sa mysql cosa bloccare? –