2013-06-08 9 views
6

Nel mio codice Rails devo confermare che un'azione è consentita solo se è rimasto più di 1 di un determinato record. Per questo motivo ho bisogno di bloccare gli aggiornamenti e quindi eseguire una lettura. Il mio codice di rotaie è simile al seguente:Rails + MySQL + Transactions + Locking, come impedire l'apertura di una transazione dallo sblocco del tavolo?

PaymentProfile.transaction do 
    profiles = PaymentProfile.lock("LOCK IN SHARE MODE").where(user_id: xxx) 

    if profiles.count > 1 
    #allow 
    else 
    #do not allow 
    end 
end 

In teoria funziona bene e blocca correttamente le righe. TUTTAVIA, se un'altra richiesta attraversa lo stesso percorso di codice che apre la transazione rimuove il blocco che ho eliminato nell'altro processo, vanificando così lo scopo del blocco.

Dalla documentazione MySQL:

Beginning a transaction also causes table locks acquired with LOCK TABLES to be released, as though you had executed UNLOCK TABLES. Beginning a transaction does not release a global read lock acquired with FLUSH TABLES WITH READ LOCK. 

risposta

2

I assumerà che un'altra richiesta sarà trattata da un altro processo, o almeno con un'altra connessione (a MySQL) (scusate non so nulla di rubino on-rails).

Un blocco acquisito da una determinata transazione non può essere rilasciato da un'altra transazione. Questo è lo scopo di una serratura. Come the manual lo mette:

UNLOCK TABLES rilascia esplicitamente eventuali blocchi di tabella detenute dalla sessione corrente

Se la mia ipotesi è corretta, non c'è nulla di cui preoccuparsi. Altrimenti, se due richieste possono utilizzare la stessa connessione contemporaneamente, c'è qualcosa di veramente strano in questa architettura ...

0

Forse, in tal caso, si dovrebbe usare un semaforo mutex (http://www.ruby-doc.org/core-2.0/Mutex.html) per evitare l'accesso simultaneo a quella risorsa condivisa (che, in questo caso, è il tuo processore PaymentProfile). In questo modo, garantirai che due processi simultanei non accedano al blocco di codice sincronizzato allo stesso tempo.

Spero che sia utile

Problemi correlati