[Pgsql-ayuda] Recuperar Datos

Alvaro Herrera alvherre@dcc.uchile.cl
Wed, 14 May 2003 21:31:22 -0400


On Wed, May 14, 2003 at 05:17:52PM -0400, e18313@uajms.edu.bo wrote:
> Primeramente agradecerte por tu tiempo, lo que ocurrio con mis datos fue
> lo siguiente entre al pgaccess y desde alli los elimine, no fue gran cosa
> pero queria si habia la posibilidad de recuperar esos datos.

Bueno, la respuesta es depende.  Hiciste algun VACUUM despues de
borrarlos?  Si lo hiciste, no tiene vuelta.

Si no lo has hecho, lo que hay que hacer es setear como "aborted" la
transaccion que borró lo datos.  Para esto tienes que cambiar el par de
bits correspondiente en el archivo correspondiente de
$PGDATA/base/data/pg_clog.

Para encontrar cual es la transaccion que eliminó los datos puedes usar
pg_filedump (http://sources.redhat.com/rhdb).  Busca el Xmax de una de
las tuplas que borraste -- esa transaccion tiene que estar marcada
"committed" en pg_clog, y tienes que dejarla como "aborted" para que la
tupla vuelva a estar viva.

Cada transaccion ocupa dos bits en un archivo del directorio pg_clog
para guardar su estado (sin completar, abortada, completa).  Lo que
necesitas es ubicar cual es el par de bits de la transaccion que te
interesa y cambiarlo de estado, a 0x02.  Ojo que hay cuatro
transacciones por byte, por lo que debes tener cuidado de no cambiar los
estados de las transacciones vecinas.

Para encontrar el archivo, el byte y el desplazamiento de bits de los
bits que necesitas cambiar, sigues estas reglas:

(todo esto está en src/backend/access/transam/clog.c)

#define CLOG_BLCKSZ			BLCKSZ

/* We need two bits per xact, so four xacts fit in a byte */
#define CLOG_BITS_PER_XACT	2
#define CLOG_XACTS_PER_BYTE 4
#define CLOG_XACTS_PER_PAGE (CLOG_BLCKSZ * CLOG_XACTS_PER_BYTE)
#define CLOG_XACT_BITMASK	((1 << CLOG_BITS_PER_XACT) - 1)

#define CLOG_XACTS_PER_SEGMENT	0x100000
#define CLOG_PAGES_PER_SEGMENT	(CLOG_XACTS_PER_SEGMENT / CLOG_XACTS_PER_PAGE)

#define TransactionIdToPage(xid)	((xid) / (TransactionId) CLOG_XACTS_PER_PAGE)
#define TransactionIdToPgIndex(xid) ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)
#define TransactionIdToByte(xid)	(TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)
#define TransactionIdToBIndex(xid)	((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)


Si vas a jugar con los archivo en pg_clog, recuerda hacer un backup
primero.

Como comentario final tendría que agregar que nunca he hecho esto, así
que no estoy seguro que funcione, pero en teoría debería.

Entrego esta solución sin garantías, así que cualquier cosa que pase es
responsabilidad tuya.  Si tu computador se eleva hasta el techo, se
inunda tu casa de alquitrán hirviendo salido de tu disco duro o aparece
una modelo vistiendo un traje de latex del demonio de FreeBSD no es
culpa mía.

Esto va con copia a la lista para que quede archivo que recuperar datos
borrados es una tarea poco trivial...

-- 
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"Un poeta es un mundo encerrado en un hombre" (Victor Hugo)