Mysql
 sql >> Database >  >> RDS >> Mysql

Come posso bloccare una riga InnoDB che non esiste ancora?

Sebbene la risposta sopra sia vera in quanto SELECT ... FOR UPDATE impedirà a sessioni / transazioni simultanee di inserire lo stesso record, questa non è la verità completa. Attualmente sto combattendo con lo stesso problema e sono giunto alla conclusione che SELECT ... FOR UPDATE è quasi inutile in quella situazione per il seguente motivo:

Una transazione / sessione simultanea può anche eseguire un SELECT ... FOR UPDATE sullo stesso valore di record / indice e MySQL lo accetterà felicemente immediatamente (senza bloccare) e senza generare errori. Naturalmente, non appena l'altra sessione lo ha fatto, anche la tua sessione non può più inserire il record. Né la tua né l'altra sessione / transazione ottengono alcuna informazione sulla situazione e pensano di poter inserire in sicurezza il record fino a quando non provano effettivamente a farlo. Il tentativo di inserimento porta quindi a un deadlock oa un errore di chiave duplicata, a seconda delle circostanze.

In altre parole, SELECT ... FOR UPDATE impedisce ad altre sessioni di inserire i rispettivi record, MA anche se fai un SELECT ... FOR UPDATE e il rispettivo record non viene trovato, è probabile che tu non possa effettivamente inserisci quel record. IMHO, che rende inutile il metodo "prima query, poi inserisci".

La causa del problema è che MySQL non offre alcun metodo per realmente bloccare i record inesistenti. Due sessioni/transazioni simultanee possono bloccare contemporaneamente record inesistenti "PER AGGIORNAMENTO", cosa che in realtà non dovrebbe essere possibile e che rende lo sviluppo notevolmente più difficile.

L'unico modo per aggirare il problema sembra essere l'utilizzo di tabelle semaforiche o il blocco dell'intera tabella durante l'inserimento. Fare riferimento alla documentazione di MySQL per ulteriori riferimenti sul blocco di intere tabelle o sull'utilizzo di tabelle semaforiche.

Solo i miei 2 cent...