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.