|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
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.
Las respuestas a estas preguntas serán publicadas en la próxima edición de General Bits.
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.
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 0005Obviamente 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!
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 impedirPara 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.
|
||||||||||||||||||||||||||||
Comments and Corrections are welcome. Suggestions and contributions of items are also welcome. Send them in!. Copyright A. Elein Mustain 2003, 2004,2005 |