PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Posso annullare una transazione che ho già commesso? (perdita di dati)

No, non puoi annullare, ripristinare o annullare un commit.

FERMARE IL DATABASE!

(Nota:se hai cancellato la directory dei dati dal filesystem, NON fermare il database. Il seguente consiglio si applica a un commit accidentale di un DELETE o simili, non un rm -rf /data/directory scenario).

Se questi dati erano importanti, INTERROMPI IL TUO DATABASE ORA e non riavviarlo. Usa pg_ctl stop -m immediate in modo che nessun checkpoint venga eseguito allo spegnimento.

Non puoi annullare una transazione una volta che è stata confermata. Dovrai ripristinare i dati dai backup o utilizzare il ripristino point-in-time, che deve essere stato configurato prima è successo l'incidente.

Se non hai impostato alcuna archiviazione PITR/WAL e non hai backup, sei davvero nei guai.

Mitigazione urgente

Una volta arrestato il database, dovresti eseguire una copia a livello di file system dell'intera directory dei dati, la cartella che contiene base , pg_clog , ecc. Copia tutto in una nuova posizione. Non fare nulla per la copia nella nuova posizione, è la tua unica speranza di recuperare i tuoi dati se non hai backup. Se possibile, fai un'altra copia su una memoria rimovibile, quindi scollega quella memoria dal computer. Ricorda, hai bisogno di assolutamente ogni parte della directory dei dati, incluso pg_xlog ecc. Nessuna parte è irrilevante.

Come eseguire esattamente la copia dipende dal sistema operativo in esecuzione. La posizione della directory dei dati dipende dal sistema operativo in esecuzione e da come hai installato PostgreSQL.

I modi in cui alcuni dati potrebbero essere sopravvissuti

Se interrompi il tuo DB abbastanza rapidamente potresti avere la speranza di recuperare alcuni dati dalle tabelle. Questo perché PostgreSQL utilizza il controllo della concorrenza multi-versione (MVCC) per gestire l'accesso simultaneo al suo spazio di archiviazione. A volte scrive nuove versioni delle righe che aggiorni nella tabella, lasciando le vecchie al loro posto ma contrassegnate come "cancellate". Dopo un po' arriva l'autovaccum e contrassegna le righe come spazio libero, in modo che possano essere sovrascritte da un successivo INSERT o UPDATE . Quindi, le vecchie versioni di UPDATE d righe potrebbero essere ancora in giro, presenti ma inaccessibili.

Inoltre, Pg scrive in due fasi. I primi dati vengono scritti nel registro write-ahead (WAL). Solo una volta che è stato scritto nel WAL e ha colpito il disco, viene quindi copiato nell'"heap" (le tabelle principali), eventualmente sovrascrivendo i vecchi dati che erano lì. Il contenuto WAL viene copiato nell'heap principale da bgwriter e da controlli periodici. Per impostazione predefinita, i checkpoint si verificano ogni 5 minuti. Se riesci a fermare il database prima che si verificasse un checkpoint e lo arresti uccidendolo a fondo, staccando la spina dalla macchina o usando pg_ctl in immediate modalità da cui potresti aver acquisito i dati prima che si verificasse il checkpoint, quindi è più probabile che i tuoi vecchi dati siano ancora nell'heap.

Ora che hai eseguito una copia completa a livello di file system della directory dei dati, puoi avviare il backup del database se davvero necessario; i dati saranno ancora spariti, ma hai fatto il possibile per darti qualche speranza di recuperarli magari. Data la scelta, probabilmente terrei chiuso il DB solo per sicurezza.

Recupero

Potrebbe essere necessario assumere un esperto nelle viscere di PostgreSQL per assisterti in un tentativo di recupero dei dati. Preparati a pagare un professionista per il suo tempo, possibilmente un bel po' di tempo.

Ho postato su questo nella mailing list di Pg e Виктор Егоров si è collegato al post di depesz su pg_dirtyread, che sembra proprio quello che vuoi, anche se non recupera TOAST ed data quindi è di utilità limitata. Provalo, se sei fortunato potrebbe funzionare.

Vedi:pg_dirtyread su GitHub.

Ho rimosso ciò che avevo scritto in questa sezione poiché è obsoleto da quello strumento.

Vedi anche Nozioni di base sull'archiviazione delle righe di PostgreSQL

Prevenzione

Vedi il mio post sul blog Prevenire il danneggiamento del database PostgreSQL.

In una nota a margine semi-correlata, se stavi usando il commit a due fasi potresti ROLLBACK PREPARED per una transazione che è stata preparata per il commit ma non completamente impegnata. Questo è il più vicino possibile al rollback di una transazione già impegnata e non si applica alla tua situazione.