Aunque todos los módulos integrados que registran en WAL tienen sus propios tipos de registros WAL, también existe un tipo de registro WAL genérico, el cual describe cambios en las páginas de una manera genérica.
Los registros WAL genéricos se ignoran durante la decodificación lógica (Logical Decoding). Si se requiere decodificación lógica para tu extensión, considera un gestor de recursos WAL personalizado (Custom WAL Resource Manager).
La API para construir registros WAL genéricos está definida en
access/generic_xlog.h e implementada
en access/transam/generic_xlog.c.
Para realizar una actualización de datos registrada en WAL utilizando la facilidad de registro WAL genérico, sigue estos pasos:
state = GenericXLogStart(relation) — inicia la
construcción de un registro WAL genérico para la relación dada.
page = GenericXLogRegisterBuffer(state, buffer, flags)
— registra un búfer para ser modificado dentro del registro WAL genérico
actual. Esta función devuelve un puntero a una copia temporal de la
página del búfer, donde se deben realizar las modificaciones. (No modifiques el
contenido del búfer directamente). El tercer argumento es una máscara de bits de flags
aplicables a la operación. Actualmente, el único flag es
GENERIC_XLOG_FULL_IMAGE, que indica que se debe incluir una imagen de página
completa en lugar de una actualización delta en el registro WAL.
Normalmente, este flag se configuraría si la página es nueva o ha sido
reescrita por completo.
GenericXLogRegisterBuffer se puede repetir si la
acción registrada en WAL necesita modificar múltiples páginas.
Aplica las modificaciones a las imágenes de página obtenidas en el paso anterior.
GenericXLogFinish(state) — aplica los cambios a
los búferes y emite el registro WAL genérico.
La construcción del registro WAL se puede cancelar entre cualquiera de los pasos anteriores llamando a
GenericXLogAbort(state). Esto descartará todos los
cambios en las copias de las imágenes de página.
Ten en cuenta los siguientes puntos al utilizar la facilidad de registro WAL genérico:
¡No se permiten modificaciones directas de los búferes! Todas las modificaciones deben
hacerse en las copias obtenidas de GenericXLogRegisterBuffer().
En otras palabras, el código que crea registros WAL genéricos nunca debería llamar a
BufferGetPage() por sí mismo. Sin embargo, sigue siendo
responsabilidad del invocador fijar/desfijar (pin/unpin) y bloquear/desbloquear (lock/unlock) los búferes en los
momentos adecuados. Se debe mantener un bloqueo exclusivo en cada búfer objetivo
desde antes de GenericXLogRegisterBuffer() hasta después de
GenericXLogFinish().
El registro de búferes (paso 2) y las modificaciones de las imágenes de página (paso 3) se pueden mezclar libremente, es decir, ambos pasos se pueden repetir en cualquier secuencia. Ten en cuenta que los búferes deben registrarse en el mismo orden en que se obtendrán los bloqueos sobre ellos durante la reproducción (replay).
El número máximo de búferes que se pueden registrar para un registro WAL genérico
es MAX_GENERIC_XLOG_PAGES. Se lanzará un error
si se supera este límite.
WAL genérico asume que las páginas a modificar tienen una distribución estándar y,
en particular, que no hay datos útiles entre
pd_lower y pd_upper.
Dado que estás modificando copias de páginas de búfer,
GenericXLogStart() no inicia una sección
crítica. Por lo tanto, puedes realizar de forma segura asignaciones de memoria, lanzamientos de errores,
etc. entre GenericXLogStart() y
GenericXLogFinish(). La única sección crítica real se encuentra
dentro de GenericXLogFinish(). Tampoco hay necesidad de
preocuparse por llamar a GenericXLogAbort() durante una salida por error.
GenericXLogFinish() se encarga de marcar los búferes como sucios (dirty)
y establecer sus LSN. No necesitas hacer esto explícitamente.
Para las relaciones no registradas (unlogged relations), todo funciona igual, excepto que no se emite ningún registro WAL real. Por lo tanto, normalmente no necesitas realizar comprobaciones explícitas para las relaciones no registradas.
La función redo de WAL genérico adquirirá bloqueos exclusivos en los búferes en el mismo orden en que fueron registrados. Después de aplicar todos los cambios, los bloqueos se liberarán en el mismo orden.
Si no se especifica GENERIC_XLOG_FULL_IMAGE para un
búfer registrado, el registro WAL genérico contiene un delta entre
la imagen de página antigua y la nueva. Este delta se basa en una comparación
byte a byte. Esto no es muy compacto en el caso de mover datos
dentro de una página, y podría mejorarse en el futuro.