E 'una condizione di gara?

1

Ho un amico che sostiene che questa è una condizione di competizione, ma ho difficoltà a capire come.

Questo è per un'applicazione web che utilizza PHP e MySQL dove gli utenti possono accedere e creare ticket, questi ticket hanno compiti che gli utenti possono aggiungere. Ogni attività ha una variabile di spesa.

Quando l'utente invia un'attività, aggiunge una riga con i dati dell'attività a una tabella. Dopo aver aggiunto la voce, calcola il tempo totale speso per tutte le attività per questo particolare ticket e aggiorna un campo in una tabella diversa con quel valore.

L'argomento esposto dal mio amico è che con molti utenti ci saranno problemi relativi alle condizioni di gara, dal momento che gli utenti aggiungono contemporaneamente compiti per i ticket.

Ma la mia difesa è che finché l'aggiornamento per il tempo totale trascorso viene eseguito dopo la query di inserimento, aggiornerà comunque il campo correttamente indipendentemente dal numero di utenti che aggiungono attività contemporaneamente.

    
posta Matt 17.03.2015 - 09:34
fonte

2 risposte

2

Se non utilizzi le transazioni, allora sì, c'è una condizione di competizione minore che può portare ad avere il valore errato per il tempo totale trascorso per un breve periodo. Si consideri ad esempio il seguente calendario di eventi:

[task 1 added]
[total selected]
                [task 2 added]
[total updated]
                [total selected]
                [total updated]

Ora il client 1 seleziona l'importo totale, ma dopo questo viene aggiunto un nuovo compito e per un breve periodo il totale contiene un valore errato. Tuttavia, subito dopo il client 2 aggiornerà il totale al valore corretto.

È possibile eliminare le attività oltre ad aggiungerle? Se è così, la situazione potrebbe diventare più complessa e richiede ulteriori analisi.

Dovresti davvero usare le transazioni in questo caso d'uso. Ciò garantisce che l'aggiornamento del totale e l'aggiunta dell'attività avvengano simultaneamente se visualizzati dall'esterno della transazione. L'utilizzo di una transazione con un adeguato livello di isolamento elimina la condizione di minore competizione.

Dovresti notare, tuttavia, che mentre le transazioni aiutano in questo caso d'uso ci sono vari livelli di isolamento della transazione e tutte le potenziali condizioni di competizione non scompaiono a meno che il tuo database non supporti realmente il livello di isolamento SERIALIZABLE e tu lo stia effettivamente utilizzando. Molti database hanno il livello di isolamento predefinito impostato su qualcosa di diverso da SERIALIZABLE e in realtà non supportano il vero livello di isolamento SERIALIZABLE mentre lo accettano silenziosamente e offrono qualcosa di peggio. Per leggere i livelli di isolamento della transazione, vedere ad es. link (questo è per PostgreSQL, non MySQL)

Per un esempio del caso in cui la condizione della competizione può verificarsi nonostante l'utilizzo delle transazioni, vedi questo tempismo:

[transaction 1 begins]
                       [transaction 2 begins]
[task 1 added]
                       [task 2 added]
[total selected]
                       [total selected, doesn't yet see transaction 1]
[total updated]
                       [total updated, waits for lock of transaction 1]
[transaction 1 commits]
                       [transaction 2 commits]

Ora la transazione 2 aggiorna il totale ma non vede ancora la riga aggiunta dalla transazione 1, quindi il totale finisce con il solo valore dell'attività 2 ma non il valore dell'attività 1. Ciò accade se non lo sei utilizzando il livello di isolamento SERIALIZABLE. Se, d'altro canto, si utilizza il livello di isolamento SERIALIZABLE su PostgreSQL recente, una delle transazioni fallirebbe a causa di un errore di serializzazione e sarebbe necessario essere pronti a riprovare.

Per risolvere il problema senza usare SERIALIZABLE, devi selezionare una riga di blocco per l'aggiornamento (il comando SQL SELECT ... FOR UPDATE):

[transaction 1 begins]
                       [transaction 2 begins]
[select for update]
                       [select for update, waits for transaction 1]
[task 1 added]
[total selected]
[total updated]
[transaction 1 commits]
                       [select for update wait done]
                       [task 2 added]
                       [total selected, doesn't yet see transaction 1]
                       [total updated, waits for lock of transaction 1]
                       [transaction 2 commits]

Non sono sicuro che MySQL supporti il vero livello di isolamento SERIALIZABLE o se sia solo l'isolamento dello snapshot. C'era almeno un po 'di lavoro da parte di Michael Cahill, ma non sono sicuro che quel lavoro si sia mai fuso con la distribuzione MySQL.

Si noti che per il corretto funzionamento delle transazioni, è necessario utilizzare un motore di database transazionale. Cioè InnoDB invece di MyISAM.

    
risposta data 17.03.2015 - 15:20
fonte
-1

No , questa non è condizione di gara.

Race condition means more than one user updating the value of same variable, and last assigned value will become the value for that variable.

Ad esempio,

if A assign value to variable X = 10, then
   B assign value to variable X = 12, then
   C assign value to variable X = 8, then

8 would became value for variable X. Means C will win.

Questa condizione di gara è effettivamente opposta alla condizione di gara del mondo reale, " Chi arriva per ultimo, VINCE ".

E nel tuo caso non esiste una tale condizione in cui più utenti stanno cercando di cambiare lo stesso record. Quindi non possiamo chiamarlo condizioni di gara.

    
risposta data 21.04.2015 - 08:09
fonte

Leggi altre domande sui tag