2010-02-01 18 views
12

Estoy escribiendo un script PHP (que también utiliza los comandos de Linux Bash) que se desarrollará a través de casos de prueba de la siguiente manera:Postgres pg_dump vertederos de base de datos en un orden diferente cada vez

estoy usando una base de datos PostgreSQL (8,4 0.2) ...

1.) Crear una base de datos 2.) Modificar el DB 3.) guardar un volcado de la base de datos de la base de datos (pg_dump)

4.) hacer pruebas de regresión repitiendo los pasos 1.) y 2.), y luego tomar otro volcado de base de datos y compararlo (diff) con el volcado de base de datos original desde el paso número 3.)

Sin embargo, estoy descubriendo que pg_dump no siempre va a volcar la base de datos de la misma manera. Va a volcar las cosas en un orden diferente cada vez. Por lo tanto, cuando hago un diff en los dos volcados de la base de datos, la comparación dará como resultado que los dos archivos sean diferentes, cuando en realidad son iguales, simplemente en un orden diferente.

¿Hay alguna manera diferente de hacer el pg_dump?

Gracias!

Respuesta

7

Es imposible obligar a pg_dump a volcar datos en un orden particular, ya que vuelca los datos en el orden de los discos, es mucho más rápido de esta manera.

Puede usar las opciones "-a-d" para pg_dump y luego "ordenar" la salida, pero las nuevas líneas en los datos harán que la salida ordenada no sea importable. Pero para una comparación básica, si algo cambió, sería suficiente.

1

No es inusual que PostgreSQL se comporte de forma no determinante: tal vez los procesos de reorganización desencadenados por temporizador o algo así ocurran en segundo plano. Además, no conozco una forma de forzar a pg_dump a reproducir una salida idéntica a bit en sucesivas ejecuciones.

Te sugiero que cambies la lógica de comparación porque es tu comparación la que se comporta mal: informa diferencias mientras que ambos volcados representan el mismo estado de la base de datos. Esto, por supuesto, significa un trabajo adicional, pero en mi opinión es la forma correcta de atacar el problema.

9

Aquí vale la pena distinguir el esquema y los datos. El esquema se descarga en un orden bastante determinista, la mayoría de los objetos alfabéticamente, restringidos por dependencias entre objetos. Hay algunos casos limitados en los que el orden no está completamente restringido y puede parecer aleatorio para un observador externo, pero eso puede solucionarse en la próxima versión.

Por otro lado, los datos se vuelcan en orden de disco. Esto es generalmente lo que quiere, porque quiere que los vertederos sean rápidos y no use cantidades insanas de recursos para hacer la clasificación. Lo que podría estar observando es que cuando "modifica la base de datos" está haciendo una ACTUALIZACIÓN, que en realidad eliminará el valor anterior y anexará el nuevo valor al final. Y eso, por supuesto, alterará su estrategia diff.

Una herramienta que podría ser más adecuada para su propósito es pg_comparator.

+0

1 Para pg_comparator que no sabía antes. –

+1

Un enlace más actualizado es http://www.coelho.net/pg_comparator/ –

1

Si están interesados ​​sólo en el esquema:

que podría hacer su mesa diff mesa por el uso de una combinación de estas opciones para volcar el esquema de una sola mesa a la vez. Luego, puede compararlos individualmente o agruparlos en un solo archivo en un orden conocido.

-s, --schema-only   dump only the schema, no data 
-t, --table=TABLE   dump the named table(s) only 

para generar la lista de tablas para alimentar a lo anterior, la consulta information_schema.tables.

11

Aquí es un script muy útil para el pre-procesamiento pg_dump de salida para que sea más adecuado para diferenciar y almacenar en el control de versiones:

https://github.com/akaihola/pgtricks

pg_dump_splitsort.py divide el volcado en los siguientes archivos:

  • 0000_prologue.sql: todo hasta la primera COPIA
  • 0001_<schema>.<table>.sql
    .
    .
    NNNN_<schema>.<table>.sql: datos para cada tabla ordenado por el primer campo
  • 9999_epilogue.sql: todo después de la última copia

Los archivos de datos de la tabla se numeran de manera simple concatenación ordenada de todos los archivos se pueden utilizar para volver a crear la base de datos:

$ cat *.sql | psql <database> 

he encontrado que una buena manera de tomar un rápido vistazo a las diferencias entre los vertederos es utilizar la herramienta de meld en todo el directorio:

$ meld old-dump/ new-dump/ 

El almacenamiento del volcado en el control de versiones también ofrece una visión decente de las diferencias. Aquí se explica cómo configurar git utilizar el color en las diferenciaciones:

# ~/.gitconfig 
[color] 
     diff = true 
[color "diff"] 
     frag = white blue bold 
     meta = white green bold 
     commit = white red bold 

Nota: Si ha creado/disminuido/tablas renombradas, recordar para eliminar todos los archivos .sql antes de post-procesamiento de la nueva volcado.

+0

¡Me ha salvado el día! :) – giaffa86

2

en mayo de 2010 un patch to pg_dump existe que pueda ser útil para todos los interesados ​​en este asunto - se añade la opción "--ordered" a esta utilidad:

Usando --ordered ordenará los datos por clave principal o índice único, si existe uno , y utilice el pedido "más pequeño" (es decir, el menor número de columnas requeridas para un pedido único).

Tenga en cuenta que --ordered podría aplastar su servidor de base de datos si intenta ordenar tablas muy grandes, por lo que debe usarlo con prudencia.

No lo probé, pero supongo que vale la pena intentarlo.

+0

Hola, Zifot, el enlace está roto, aún pasaron 2 años, me gustaría probarlo pero no puedo encontrar otras referencias. ¿Podría proporcionar el enlace de trabajo? Gracias. – Igor

+0

@Igor, acabo de actualizar el enlace. – zifot

+0

Un parche/adición muy interesante que desafortunadamente no llegó al lanzamiento. –

0

Si el rendimiento es menos importante que el fin puede usar:

COPY (select * from your_table order by some_col) to stdout 
     with csv header delimiter ','; 

Ver COPY (9.5)

Cuestiones relacionadas