Devo bloccare le righe nel mio DB cloud mentre vengono modificate da un utente


12

Sto creando un'applicazione desktop che persiste i dati nel cloud. Una preoccupazione che ho è un inizio a modificare un elemento nell'applicazione e lasciarlo per un po 'facendo in modo che i dati diventino obsoleti. Questo può ovviamente accadere anche se 2 persone provano a modificare lo stesso oggetto contemporaneamente. Quando hanno terminato la loro modifica e vogliono salvare i dati, avrei bisogno di sovrascrivere ciò che esiste attualmente nel database o verificare che abbiano iniziato la modifica dopo l'ultima modifica e costringerli a scartare le loro modifiche o forse dare loro l'opzione di rischiare sovrascrivendo i cambiamenti di qualcun altro.

Ho pensato di aggiungere un campo is_lockede lock_timestampla tabella DB. Quando un utente inizia a modificare l'elemento, la riga cambia is_lockedin true e imposta il timestamp di blocco sull'ora corrente. Avrei quindi un po 'di tempo per il quale si tiene il blocco (es. 5 minuti). Se qualcun altro prova a modificare l'elemento, riceverà un messaggio che dice che l'oggetto è bloccato e quando il blocco scade automaticamente. Se l'utente si allontana durante la modifica, il blocco scadrà automaticamente dopo un periodo di tempo relativamente breve e una volta fatto l'utente verrà avvisato che il blocco è scaduto e sarà costretto a riavviare la modifica dopo l'aggiornamento dei dati.

Sarebbe un buon metodo per prevenire la sovrascrittura di dati non aggiornati? È eccessivo (non mi aspetto che l'applicazione venga utilizzata da più persone contemporaneamente su un singolo account).

(Un'altra preoccupazione che ho è che 2 persone ottengano un lucchetto per lo stesso oggetto, tuttavia credo che sia una condizione di gara con cui mi sento a mio agio.)


1
"Un'altra preoccupazione che ho è che 2 persone ottengano un lucchetto per lo stesso oggetto, tuttavia credo che sia una condizione di gara con cui mi trovo a mio agio" - l'utilizzo di una transazione di database attorno all'acquisizione del lucchetto dovrebbe impedire tali condizioni di gara.
Jules

La maggior parte dei motori di database (almeno di tipo relazionale) ha un supporto integrato per questo. È un concetto molto comune nel mondo RDBMS e persino i database "giocattolo" lo gestiscono abbastanza bene, dato che gli dici che vuoi un blocco ottimistico o pessimistico. Ad ogni modo, non credo sia qualcosa che devi costruirti in alcun modo: controlla le opzioni sul tuo motore db per vedere come lavorarci.
jleach

Il fatto che l'applicazione sia un'applicazione desktop (un client fat ) non fa molta differenza. Può essere progettato allo stesso modo di un'applicazione server multiistanza ad alta disponibilità.
Hosam Aly,

Risposte:


19

Una cosa che ti aiuterà qui è la terminologia. Quello che stai descrivendo qui si chiama 'blocco pessimistico'. La principale alternativa a questo approccio è il "blocco ottimistico". Nel blocco pessimistico, ogni attore deve bloccare il record prima di aggiornarlo e rilasciare il blocco al termine dell'aggiornamento. Nel blocco ottimistico, supponi che nessun altro stia aggiornando il record e prova. L'aggiornamento non riesce se il record è stato modificato da un altro attore.

Il blocco ottimistico è generalmente preferibile se la possibilità che due attori aggiornino la stessa cosa contemporaneamente è bassa. Il pessimistico viene in genere utilizzato quando tale possibilità è elevata o è necessario sapere che l'aggiornamento sarà in grado di avere successo prima dell'inizio. Nella mia esperienza, il blocco ottimistico è quasi sempre preferibile perché ci sono molti problemi inerenti al blocco pessimistico. Uno dei maggiori problemi è toccato nella tua domanda. Gli utenti possono bloccare un record per la modifica e quindi partire per pranzo. La tua mitigazione ti aiuterà, ma l'esperienza dell'utente non sarà migliore dell'approccio ottimista e probabilmente peggiorerà molto. Ad esempio, un utente apre un record, inizia ad aggiornarlo e il suo capo si presenta alla propria scrivania. Un altro utente tenta di modificare il record. È chiuso. Il secondo utente continua a provare e dopo 5 minuti, il blocco scade e il secondo utente aggiorna il record. Il primo utente torna sullo schermo, prova a salvare e gli viene detto che ha perso il blocco. Ora nello stesso scenario con tutto lo stesso tranne l'uso del blocco ottimistico, l'esperienza del primo utente è praticamente la stessa, ma il secondo utente non aspetta 5 minuti.

Lo schema che presenterai sarebbe notevolmente migliorato implementando il blocco ottimistico per il valore di blocco, ma il mio sospetto è che il blocco ottimistico sia probabilmente OK per tutto e puoi sbarazzarti del campo is_locked.

Non fornisci quale "cloud DB" stai utilizzando. Probabilmente dovresti esaminare le funzionalità di questo per vedere se ci sono funzionalità integrate per questo prima di implementare la tua soluzione.

Ecco la ricetta di base: invece di un campo is_locked, disporre di un campo del numero di versione. Quando si recupera il record, si estrae la versione corrente del record. Quando si aggiorna, l'aggiornamento dipende dal campo della versione corrispondente a quello recuperato e lo si incrementa in caso di successo. Se la versione non corrisponde, l'aggiornamento non ha alcun effetto e viene segnalato come un errore.


Questa è una risposta molto utile Puoi spiegare perché il blocco pessimistico è scoraggiato quando c'è una piccola possibilità di "collisioni". È solo perché richiede di andare al database anche solo per iniziare la modifica, o per una maggiore complessità o per qualche altro motivo? Grazie!
yitzih,

3
@yitzih Alcune letture suggerite: Fowler et al, Patterns of Enterprise Application Architecture . C'è un intero capitolo su questa domanda, con una buona discussione di tutte le opzioni e le ragioni per sceglierle.
Jules

2
@Jimmy - La tua risposta va bene. In alcuni casi, la segnalazione di un errore potrebbe non essere sufficiente. Prendi in considerazione un caso in cui un utente impiega qualche minuto ad aggiornare un record. In tal caso, il solo fallimento potrebbe non essere abbastanza buono, si potrebbe desiderare di dare all'utente la possibilità di unire le proprie modifiche in volo con quelle commesse dall'altro utente. Avrei dovuto dire che il blocco ottimistico potrebbe richiedere la risoluzione dei conflitti in base alle vostre esigenze.
Jon Raynor,

3
Vale la pena ricordare che il blocco pessimistico è molto più facile da spiegare al cliente. Se si scrive un messaggio che il client non può accedere al record perché è attualmente in fase di modifica da parte di un altro, il client comprende entrambi bene e generalmente lo accetta. Se invece dici al cliente dopo aver salvato quel salvataggio non è stato possibile perché era già stato aggiornato da un altro utente, 7/10, il client sarà frustrato e / o si aspetterà spiegazioni per questo strano comportamento del programma.
Neil,

2
@Neil Questo è vero e penso che sia spesso il motivo per cui il blocco pessimistico viene utilizzato quando l'ottimismo è più appropriato. Spesso il flusso di lavoro rende molto improbabile che vi sia una collisione.
JimmyJames,

0

Dalla risposta di @ JimmyJames , possiamo vedere come la domanda riguarda davvero l'esperienza dell'utente .

Tutto dipende dal contesto. Quanto tempo e sforzo ci vuole per aggiornare un record? Con quale frequenza più utenti desiderano aggiornare lo stesso documento?

Ad esempio, se gli utenti di solito impiegano alcuni secondi per aggiornare il record e c'è poca contesa, probabilmente il blocco ottimistico è la strada da percorrere. Nel peggiore dei casi, un utente dovrà dedicare qualche secondo in più, forse fino a un minuto, per aggiornare un documento.

Se il tuo documento è molto controverso ma ben strutturato, forse puoi consentire loro di bloccare singoli campi con incrementi di 30 secondi, mostrando un timer o una notifica discreta per consentire loro di estendere il blocco.

Tuttavia, se i tuoi utenti trascorrono una notevole quantità di tempo o sforzi, dovresti prendere in considerazione altri approcci. Il tuo disco è ben strutturato? Potresti mostrare agli utenti un confronto (una diff) tra la versione sul server e la versione che stanno cercando di salvare? Puoi evidenziare le differenze? Puoi lasciarli unire le modifiche? Pensa all'esperienza che vuoi avere con i tuoi strumenti di controllo del codice sorgente. Davvero non vuoi essere costretto a scrivere di nuovo tutto quel codice!

Puoi consultare Google Documenti per ulteriore ispirazione. Forse puoi mostrare agli utenti una notifica che una nuova versione è stata salvata. Forse puoi mostrare loro quante persone hanno il disco aperto in modo che possano scegliere di tornare in un momento meno controverso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.