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.