En Postgres, estoy sacando una transacción de LECTURA REPETIBLE para obtener una vista consistente de la base de datos en el momento en que comienza la transacción. Me gustaría saber el LSN del POV de esta transacción para poder configurar una ranura de replicación en este LSN en el mismo empate para que una vez que termine con la transacción pueda configurar la replicación lógica en el LSN y recibir todas las actualizaciones a la base de datos que sucedió después de que comenzó la transacción.
Mi expectativa era que el LSN no cambiaría una vez dentro de la transacción (ya que otras conexiones estaban realizando actualizaciones, etc.), sin embargo, varias llamadas pg_current_wal_lsn en la transacción dieron como resultado un LSN diferente cada vez.
¿Hay alguna forma de determinar el último LSN visto desde el punto de vista de la transacción?
Para obtener un poco más de contexto, me gustaría configurar la replicación lógica en una base de datos, pero primero debo operar con los datos que existen en la base de datos antes de configurar la ranura de replicación. Debo suponer que los segmentos WAL anteriores se han purgado, por lo que no espero ver todos los datos en la base de datos a través de la replicación lógica y, como resultado, necesito una forma de operar primero con los datos existentes y luego transmitir todo lo que pasa. Esperemos que eso tenga sentido.
Gracias por adelantado.
Lo que se fija para una transacción de REPEATABLE READ no es la posición WAL, ya que dicha transacción puede realizar modificaciones de datos. Es la instantánea , que determina qué versiones de fila puede ver.
Una instantánea consiste en una ID de transacción mínima (la transacción puede ver cualquier fila creada por transacciones anteriores), una ID de transacción máxima (la transacción no puede ver nada más nuevo que eso) y la lista de las ID de todas las transacciones simultáneas.
Ahora, si tiene una transacción de REPEATABLE READ READ ONLY , tiene sentido solicitar la posición en la que se inserta WAL en el momento en que se toma la instantánea, por lo que podría consultar
SELECT pg_current_wal_insert_lsn();como la primera declaración en su transacción.
Sin embargo, existe una condición de carrera: primero PostgreSQL toma la instantánea y luego ejecuta la consulta. Entre esos momentos, una transacción simultánea podría realizar modificaciones de datos que no son visibles para la instantánea, pero antes del LSN que obtiene de la función.
La solución es utilizar la decodificación lógica . Como dice la documentación :
Cuando se crea una nueva ranura de replicación utilizando la interfaz de replicación de transmisión (consulte
CREATE_REPLICATION_SLOT), se exporta una instantánea (consulte la Sección 9.27.5 ), que mostrará exactamente el estado de la base de datos después de lo cual todos los cambios se incluirán en el flujo de cambios. Esto se puede usar para crear una nueva réplica usandoSET TRANSACTION SNAPSHOTpara leer el estado de la base de datos en el momento en que se creó la ranura. Esta transacción se puede usar para volcar el estado de la base de datos en ese momento, que luego se puede actualizar usando el contenido de la ranura sin perder ningún cambio.
Entonces, lo hace al revés: primero crea una ranura de replicación lógica, luego inicia una transacción REPEATABLE READ y configura su instantánea para que vea los datos correctos.