Richieste transazionali e ripristino degli errori nei sistemi di database

4

Diciamo che abbiamo a che fare con una versione abbastanza semplice e originale di un database, che utilizza la versione classica dei log redo-undo per il ripristino degli errori. Per una richiesta "classica" che trasferisce un importo da un account a un altro, i log scritti in ogni fase della transazione sono i seguenti:

1. TRANSACTION START         ----->    START TRANSACTION   XID1
2. READ A1                   ----->    
3. READ A2                   ----->
4. WRITE (A1,A+10)           ----->    WRITE [A1,100,110]  XID1
5. WRITE (A2,A2-10)          ----->    WRITE [A2,200,190]  XID1
6. COMMIT                    ----->    COMMIT TRANSACTION  XID1

Ad esempio, se c'è un errore di sistema tra l'azione 4 e amp; 5, quando il database viene riavviato, riconoscerà dai registri che la transazione XID1 non è stata eseguita e procederà con l'annullamento di tutte le scritture nel registro (utilizzando i valori precedenti).

Ora, la mia domanda. Suppongo che quando si raggiunge l'azione 6, il sistema prima persista il commit della transazione, scrivendo il log COMMIT e quindi risponde al client, informando che la richiesta è stata elaborata correttamente. Nel caso in cui si verifichi un errore di sistema dopo che il sistema ha scritto il registro COMMIT, ma prima di rispondere al client, cosa succede? Seguendo la mia logica, ciò significherebbe che il sistema dopo il ripristino considererebbe la transazione come impegnata (poiché esiste un record COMMIT) e procederebbe senza la necessità di eseguire undo-redo. Tuttavia, l'utente è stato probabilmente informato che la transazione è stata ABORTED, mentre la transazione è stata completata con successo.

  • Mi manca qualcosa nel mio intero approccio?
  • In che modo i sistemi RDBMS comuni gestiscono questo problema?

P.S.: I now that log records are not written immediately to disk actually, but I over-simplified the example for the sake of brevity.

    
posta Dimos 23.12.2016 - 21:55
fonte

1 risposta

1

Tornando con un po 'di ricerca personale, ma ancora aperto a nuove risposte. Ingenuamente, si potrebbe pensare che una soluzione potrebbe essere quella di aggiungere un nuovo livello di registrazione (se il cliente ha ricevuto o meno la risposta). Il riconoscimento dovrebbe essere costruito nel livello applicazione, poiché TCP non supporta qualcosa di simile . Tuttavia, avremmo spostato ulteriormente la condizione di gara, considerando che una partizione di rete poteva portare il client a ricevere la risposta, ma il server assumeva il contrario, ripristinando la transazione. Di conseguenza, penso che questo sia radicato nel teorema di impossibilità FLP , ovvero il fatto che il server non può sapere se si è precedentemente verificato un arresto anomalo o che la connessione è stata molto molto lenta (e il messaggio è stato ricevuto dall'altra parte). In breve, l'unico approccio che ho trovato per questo problema è il seguente:

  • Considerare il sistema (server-client) come un sistema distribuito. In questo modo, un commit di transazione significa che i nuovi dati sono visibili e duraturi per tutte le letture future da tutti i client (esclusa la transazione corrente). Di conseguenza, il client dovrebbe eseguire una lettura di follow-up, nel caso in cui la connessione è stata persa per confermare se la transazione è stata commessa o ripristinata. Per ottenere ciò, le operazioni client devono essere rese idempotenti. Questo approccio è ben descritto nella documentazione di VoltDB , dove afferma:

Note this isn’t really a VoltDB problem, but a problem with any stateful system that uses a network somewhere

    
risposta data 25.12.2016 - 16:02
fonte

Leggi altre domande sui tag