Estoy tratando de obtener cuándo se modificó mi tabla al verificar la fecha de modificación del archivo como se describe en esta respuesta . Pero el resultado no siempre es correcto. La fecha de modificación del archivo se actualiza en varios minutos después de actualizar mi tabla. ¿Es correcto el comportamiento? ¿PostgreSQL almacena las modificaciones de la tabla en algún caché y luego lo vacía en el disco duro?
Entonces, ¿cómo obtengo la fecha correcta de la última modificación de una tabla (supongamos que las modificaciones de vacío automático también están bien)?
Yo uso PostgreSQL 9.2 en Linux Centos 6.2 x64.
postgresql
madeja
fuente
fuente
Respuestas:
No existe un registro confiable y automático de la última hora modificada de una tabla. Usar el relfilenode está mal por muchas razones:
Las escrituras se registran inicialmente en el registro de encabezado de escritura (WAL), luego , lentamente, en el montón (los archivos de la tabla). Una vez que el registro está en WAL, Pg no se apresura a escribirlo en el montón, y es posible que ni siquiera se escriba hasta el próximo punto de control del sistema;
Las tablas más grandes tienen múltiples horquillas, tendría que verificar todas las horquillas y elegir la marca de tiempo más nueva;
Un simple
SELECT
puede generar actividad de escritura en la tabla subyacente debido a la configuración de bits de pista;autovaccum y otro mantenimiento que no cambia los datos visibles del usuario todavía modifica los archivos de relación;
Algunas operaciones, como
vaccum full
, reemplazarán el relfilenode. Es posible que no sea lo que espera si está tratando de verlo simultáneamente sin tomar un bloqueo adecuado.Algunas opciones
Si no necesita confiabilidad, puede usar la información en
pg_stat_database
ypg_stat_all_tables
. Estos pueden darle el tiempo del último restablecimiento de estadísticas y las estadísticas de actividad desde el último restablecimiento de estadísticas. No te dice cuándo fue la actividad más reciente, solo que fue desde el último restablecimiento de estadísticas, y no hay información sobre lo que sucedió antes de que se restablecieran las estadísticas. Entonces es limitado, pero ya está ahí.Una opción para hacerlo de manera confiable es usar un disparador para actualizar una tabla que contiene los últimos tiempos modificados para cada tabla. Tenga en cuenta que al hacerlo se serializarán todas las escrituras en la tabla , destruyendo la concurrencia. También agregará un poco de sobrecarga a cada transacción. No lo recomiendo
Una alternativa un poco menos horrible es usar
LISTEN
yNOTIFY
. Haga que un proceso de demonio externo se conecte a PostgreSQL yLISTEN
para eventos. UseON INSERT OR UPDATE OR DELETE
disparadores para enviar mensajes deNOTIFY
correo electrónico cuando una tabla cambia, con la tabla oid como la carga útil de notificación. Estos se envían cuando se confirma la transacción. Su demonio puede acumular notificaciones de cambio y perezosamente escribirlas de nuevo en una tabla en la base de datos. Si el sistema falla, pierde su registro de las modificaciones más recientes, pero está bien, solo trata todas las tablas como recién modificadas si está iniciando después de un bloqueo.Para evitar el peor de los problemas de concurrencia, puede registrar las marcas de tiempo de cambio utilizando un
before insert or update or delete or truncate on tablename for each statement execute
disparador, generalizado para tomar la relación oid como parámetro. Esto insertaría un(relation_oid, timestamp)
par en una tabla de registro de cambios. Luego, tiene un proceso auxiliar en una conexión separada, o su aplicación lo llama periódicamente, agrega esa tabla para obtener la información más reciente, la fusiona en una tabla resumen de los cambios más recientes y trunca la tabla de registro. La única ventaja de esto sobre el enfoque de escuchar / notificar es que no pierde información sobre el bloqueo, pero también es menos eficiente.Otro enfoque podría ser la de escribir una función de extensión de C que los usos (por ejemplo)
ProcessUtility_hook
,ExecutorRun_hook
, etc a cambios en la tabla de trampas y las estadísticas de actualización pereza. No he mirado para ver cuán práctico sería esto; Eche un vistazo a las diversas opciones de _hook en las fuentes.La mejor manera sería parchear el código de estadísticas para registrar esta información y enviar un parche a PostgreSQL para incluirlo en el núcleo. No solo comience escribiendo código; plantee su idea sobre los piratas informáticos una vez que lo haya pensado lo suficiente como para tener una forma bien definida de hacerlo (es decir, comience leyendo el código, no solo publique preguntando "¿cómo ...?"). Podría ser bueno agregar los últimos tiempos actualizados
pg_stat_...
, pero tendría que convencer a la comunidad de que valía la pena los gastos generales o proporcionar una forma de hacer un seguimiento opcional, y tendría que escribir el código para mantener las estadísticas y envíe un parche , porque solo alguien que quiera esta función se molestará con eso.Como lo haría
Si tuviera que hacer esto y no tuviera tiempo de escribir un parche para hacerlo correctamente, probablemente usaría el enfoque de escuchar / notificar descrito anteriormente.
Actualización para las marcas de tiempo de confirmación de PostgreSQL 9.5
Actualización : PostgreSQL 9.5 tiene marcas de tiempo de confirmación . Si los ha habilitado
postgresql.conf
(y también lo hizo en el pasado), puede verificar la marca de tiempo de confirmación de la fila con el mayorxmin
para aproximar la última hora modificada. Es solo una aproximación porque si se han eliminado las filas más recientes, no se contarán.Además, los registros de marca de tiempo de confirmación solo se mantienen durante un tiempo limitado. Entonces, si desea saber cuándo se modifica una tabla que no se modifica mucho, la respuesta será efectivamente "no sé, hace un tiempo".
fuente
PostgreSQL 9.5 nos permite rastrear la última confirmación modificada.
Verifique que la confirmación de seguimiento esté activada o desactivada utilizando la siguiente consulta
Si devuelve "ON", vaya al paso 3; de lo contrario, modifique postgresql.conf
Cambio
a
Reiniciar el sistema
Repita el paso 1.
Use la siguiente consulta para rastrear la última confirmación
fuente
sudo service postgresql restart
.Sí, esto puede esperarse: los datos sobre el cambio se almacenan en el registro de transacciones de inmediato. Los archivos de datos se pueden actualizar con checkpoint_timeout delay (el valor predeterminado es 5 minutos). Postgres no se mantiene de forma permanente en ningún momento que usted solicite.
fuente
Tengo casi el mismo requisito para mantener un caché de algunas tablas en una aplicación cliente. Digo casi , porque realmente no necesito saber la hora de la última modificación, sino solo para detectar si algo ha cambiado desde la última vez que se sincronizó el caché.
Aquí está mi enfoque:
Siempre que tenga una columna
id
(PK),created_on
(marca de tiempo de inserción) yupdated_on
(actualizar marca de tiempo, puede ser NULL) en cada tabla, puedeSi concatena esto y antepone el número de filas, puede crear una etiqueta de versión que se vea
count:id#timestamp
, y será única para cada versión de los datos en la tabla.fuente