varlena
varlena
PostgreSQL Training,
Consulting & Support
General Bits
By A. Elein Mustain


29-Sep-2003 Edición: 45

Archives | General Tidbits | Google General Bits | Docs | Castellano | Português | Subscriptions | Notifications

General Bits General Bits es una publicación periódica escrita con información desde la lista de PostgreSQL, pgsql-general.
Para saber más sobre pgsql-general y PostgreSQL, visite www.PostgreSQL.org.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Juego de PostgreSQL ... no tan sencillo!
¡Oh, no! ¡Es un examen! 26-Sept-2003

Estas son preguntas específicas sobre comportamiento de PostgreSQL. Las respuestas pueden encontrarse en varias ediciones de General Bits y en la documentación actual de la versión 7.3.

Este examen es sólo para divertirse y aprender. Inténtelo. Hágame saber si fue fácil o difícil, pero diviértase.

  • 1. ¿Qué retorna SELECT coalesce( x, y ); cuando:
    • a. x es NULL, y es 16?
    • b. x es 16, y es NULL?
    • c. x es NULL, y es NULL?
    • d. x es 16, y es 17?

  • 2. ¿Usarán un índice estas cláusulas WHERE si existe en la columna?
    • a. WHERE timestamp_value = '12/31/59'
    • b. WHERE bigint_value = 3
    • c. WHERE text_value LIKE '% the %'
    • d. WHERE text_value in ( 'val_uno', 'val_dos', 'val_tres')
    • e. ¿Cuál de ellos entregará un resultado inesperado?

  • 3. ¿Cuál será la cláusula ORDER BY cuando desee ordenar los NULLs de una columna al principio, pero que el resto de las columnas conserve su orden regular?
    • a. ORDER BY NULL
    • b. ORDER BY columna WITH NULL, columna
    • c. ORDER BY columna IS NOT NULL ASC
    • d. ORDER BY columna IS NOT NULL DESC, columna
    • e. ORDER BY columna

  • 4. En postgresql.conf, max_fsm_relations debería definirse como
    • a. 10
    • b. El número máximo de conexiones permitidas
    • c. La cantidad total de tablas en todas las bases de datos
    • d. El tamaño de cache libre en el disco duro

  • 5. El tipo timestamp with timezone se almacena con:
    • a. huso horario UTC
    • b. el huso horario del servidor
    • c. el huso horario del cliente
    • d. el huso horario especificado

  • 6. ¿Cuales de las siguientes palabras no deberían usarse como identificador en PostgreSQL?
      ARE BEGIN CURRENT_ROLE DEFAULT
      IS MOVE NOT OFFSET
      OPERATOR PRIMARY SOME UNDER

  • 7.1 RULES deberían ser usadas para funcionalidad aplicable a:
  • 7.2 TRIGGERS deberían ser usados para funcionalidad aplicable a:
    • a. una consulta
    • b. cada registro
    • c. vistas (views)
    • d. funciones

  • 8. Una función plpgsql se ejecuta
    • a. en el servidor
    • b. en la aplicación cliente
    • c. en psql
    • d. en cualquiera, el cliente o el servidor

  • 9. Una función creada con IMMUTABLE significa que
    • a. la función nunca cambiará
    • b. la función siempre retornará los mismos resultados para los mismos argumentos
    • c. la función nunca arrojará un error
    • d. la función retorna null si recibe algún argumento null

  • 10. Una función creada con STRICT significa que
    • a. no debería ser guardada en cache
    • b. debería arrojar un error ante cualquier falla
    • c. no se ejecutará si recibe algún argumento null
    • d. siempre retornará un resultado no null

Las respuestas a estas preguntas serán publicadas en la próxima edición de General Bits.

Editor: elein at varlena.com

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Almacenamiento doble
[GENERAL] update field using substrings of another field 22-Sep-2003

Se desea una tabla que contenga una columna con un número telefónico sin formato y otra columna con el número telefónico con formato. La pregunta es cómo definir uno desde el otro para asegurar que siempre son "el mismo". Se sugirió que el número sin formato podía convertirse en el otro usando complicadas funciones de manejo de subcadenas. A su vez, esto podía almacenarse en la segunda columna usando un trigger.

Este problema ilustra la principal razón por la cual no es una buena idea almacenar la misma información dos veces. Para asegurar que los valores se mantengan sincronizados, se requieren complicadas verificaciones, triggers y formateo. A menos que las verificaciones se hagan completamente libres de fallas, de alguna manera en algún momento uno de los valores va a ser actualizado y el otro no.

El requerimiento real aquí es proveer el número telefónico tanto en su forma plana como con formato. Esto se puede hacer fácilmente usando sólo funciones de formateo. La primera consulta más abajo entregará el número sin formato. La segunda entregará el número con formato, y la tercera entregará ambos. Se asume que el teléfono se almacena como numeric. Si no, hágale un cast a numeric.

	select nombre, apellido, fono from addresses;
	select nombre, apellido, to_char( fono, 'FM(999)999-999') from addresses;
	select nombre, apellido, fono, to_char( fono, 'FM(999)999-999') from addresses;

Se puede crear una vista (view) para recuperar la versión con formato fácilmente si necesita hacerse con frecuencia. El dato base, es decir el número de teléfono, sólo necesita almacenarse una vez, eliminando la necesaria verificación y la posibilidad de tener fuera de sincronía las versiones con y sin formato. Esto también muestra la distinción entre los datos y la salida formateada.

Contribuyeron: Dave [Hawk-Systems] dave at hawk-systems.com, Doug McNaught doug at mcnaught.org, Tom Lane tgl at sss.pgh.pa.us, Andreas Fromm Andreas.Fromm at physik.uni-erlangen.de

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Una Recuperación Exitosa
[GENERAL] Database Recovery Procedures 16-Sep-2003

A todos nos gustan las buenas historias con finales felices. Pero empiezan mal ... Por primera vez en seis años, una o varias tablas fueron corrompidas porque un disco se llenó en el servidor. Idealmente, los datos deberían poder recuperarse en lugar de tener que recurrir al respaldo.

Primero un "SELECT * ..." reveló que el servidor no podía iniciarse. Estos eran los mensajes de error:

	LOG:  ReadRecord: unexpected pageaddr 5/27498000 in log file 5, segment 45,
	offset 4816896
	LOG:  redo is not required
	PANIC:  XLogWrite: write request 5/2D498000 is past end of log 5/2D498000
	DEBUG:  reaping dead processes
	LOG:  startup process (pid 17031) was terminated by signal 6
	LOG:  aborting startup due to startup process failure

Nuestro héroe, Tom, sugiere que la falla de inicialización es un problema en 7.3.3 y que una actualización a 7.3.4 sería apropiada. Esta actualización no requiere un respaldo y recuperación (¡lo cual sería imposible!) y por lo tanto es posible actualizar fácilmente a 7.3.4. Hecho eso, es posible iniciar el servidor y se puede analizar el problema más a fondo.

Un "SELECT * ... LIMIT 5" de la tabla que se sabe corrupta ahora entrega este error:

	PANIC:  read of clog file 5, offset 16384 failed: Success
	server closed the connection unexpectedly
	        This probably means the server terminated abnormally
	        before or while processing the request.
	The connection to the server was lost. Attempting reset: Failed.
	!#
El pronóstico no se ve bien en este punto. Sin embargo, en respuesta a los mensajes de error, se piden los nombres y tamaños de los archivos en el directorio $PGDATA/pg_clog. Esto muestra:
	-rw-------    1 postgres users      262144 Jul 20 15:53 0000
	-rw-------    1 postgres users      262144 Jul 31 12:57 0001
	-rw-------    1 postgres users      262144 Aug 12 17:32 0002
	-rw-------    1 postgres users      262144 Aug 26 00:15 0003
	-rw-------    1 postgres users      262144 Sep  9 23:44 0004
	-rw-------    1 postgres users       16384 Sep 10 21:21 0005
Obviamente hay algo mal con el archivo 0005. Nótese que la posición que causó el panic es la misma que el tamaño del archivo. El servidor está tratando de leer más allá del fin de archivo en busca de una transacción que pg_clog no registra. pg_clog lleva la pista a los estados de las transacciones pasadas. Se deduce que probablemente el archivo 0005 de pg_clog quedó corto por el problema de espacio en disco.

La siguiente sugerencia es que el servidor sea desactivado y que el archivo sea artificialmente extendido, agregando una página de 8K de 0s al final. Esto al menos aliviará el problema de tratar de leer más allá del fin de archivo. Agregar más de una página podría ser necesario, y si los datos son recuperados, una buena revisión de su consistencia es imperativa.

Para agregar ceros al archivo se usó el siguiente comando. Se asume que /dev/zero es la fuente de 0s del sistema. dd, que copia datos binarios, se usa para escribir 8K de datos. La entrada viene de /dev/zero, y la salida debe ser agregada al final del archivo problema de pg_clog.

	dd bs=8k count=1 < /dev/zero >> $PGDATA/pg_clog/0005

Luego de esta operación, se descubre que efectivamente todos los datos de las tablas corruptas están presentes. Y así todos pueden soltar un suspiro de alivio.

Esta no es una técnica que deba ser intentada livianamente. Esta secuencia particular de mensajes de error llevaron a esta solución particular. ¡Si tiene dudas, no dude en pedir ayuda!

Contribuyeron: Keith C. Perry netadmin at vcsn.com, Tom Lane tgl at sss.pgh.pa.us

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Llave Foránea autoreferida
[SQL] weird(to me) request 25-Sep-2003

Esta es otra variante del ejemplo estándar de la tabla con personas que contiene padres e hijos. La tabla contiene a toda la gente individualmente, pero los hijos tienen referencia a uno de los padres. Este es un ejemplo usual de herencia; en este caso, no se usará herencia. En lugar de eso, se usará simple integridad referencial.

El caso real en cuestión es una tabla de cuentas. Cada cuenta puede tener una cuenta maestro. Si tiene una cuenta maestro, debe ser un registro en la tabla de cuentas.

	cuenta    cuenta_maestro  detalles
	1         NULL            ...
	2         NULL            ...
	4         2               ...
	5         2               ...
	6         3               ... <-- Este es el caso que se debe impedir
Para asegurar que cada cuenta maestro, si está presente, sean cuentas legítimas, defina una llave foránea en la cuenta_maestro.
	ALTER TABLE cuentas ADD CONSTRAINT 
	mi_auto_fk FOREIGN KEY (cuenta_mastro) REFERENCES cuentas (cuenta);
Esta restricción permite que cuenta_maestro sea NULL, pero cuando no es NULL, el valor será un número de cuenta válido.

Contribuyeron: Larry Rosenman ler at lerctr.org, Adam Wieckowski adam-wieckowski at tlen.pl, Richard Huxton dev at archonet.com


Comments and Corrections are welcome. Suggestions and contributions of items are also welcome. Send them in!.
Copyright A. Elein Mustain 2003, 2004,2005

Google
Search General Bits & varlena.com Search WWW