En este documento se describe cómo usar la función de marca de tiempo de confirmación para hacer un seguimiento de la fecha y la hora en las que se hacen cambios en los registros de tu base de datos. Si tienes una base de datos grande con muchas transacciones que cambian registros y quieres registrar los cambios realizados en los conjuntos de datos, la función de marca de tiempo de confirmación simplifica esta tarea.
A través de una serie de ejemplos de código, este documento muestra cómo reescribir el lenguaje de manipulación de datos (DML) para crear un registro de cambios. En este documento se amplía la información del artículo Usar marcas de tiempo de confirmación de Cloud Spanner para crear un registro de cambios con Go. En él se muestran los métodos con Java y JDBC. La lógica se representa en SQL en lugar de como objetos de cliente de Spanner.
Cómo funcionan las tablas
Supongamos que tienes una tabla de hechos llamada msgs
y una tabla de historial llamada msg_history
. Cada vez que se modifique la tabla de hechos, quieres guardar simultáneamente un registro en la tabla msg_history
. Puede usar el contenido de la tabla de historial más adelante para otros fines, como auditorías o como fuente de eventos.
La tabla msgs
contiene los hechos, representados por un ID de transacción (id
) y el mensaje (msg
). La declaración en lenguaje de definición de datos (DDL) que se usa para crear la tabla es similar a la siguiente:
CREATE TABLE msgs (
id INT64,
msg STRING(MAX),
) PRIMARY KEY (id)
La tabla msg_history
contiene el historial de transacciones. El siguiente DDL crea la tabla del historial. La columna ts
almacena la marca de tiempo de la confirmación.
CREATE TABLE msgs_history (
id INT64,
ts TIMESTAMP OPTIONS (allow_commit_timestamp=true),
previous_msg STRING(MAX)
) PRIMARY KEY (ts, id)
Los ejemplos
En lugar de escribir solo en la tabla de hechos, debes hacer la operación en la tabla de historial en la misma transacción. El controlador JDBC de Spanner admite la declaración del inicio y el final de una transacción, que es una operación JDBC estándar.
Paso 1: Reescribe las operaciones de inserción
El primer paso es reescribir las operaciones de insert
del siguiente formulario:
insert into msgs (id, msg) values (1, 'a real msg')
Cambia las inserciones para que tengan el siguiente aspecto:
insert into msgs_history (id, previous_msg, ts) values (1, Null, PENDING_COMMIT_TIMESTAMP()); insert into msgs (id, msg) values (1, 'a real msg');
Este es el código Java:
// insert into history stmt.executeUpdate( "insert into msgs_history (id, previous_msg, ts)" + " values (1, Null, PENDING_COMMIT_TIMESTAMP())"); // insert into real table stmt.executeUpdate("insert into msgs (id, msg)" + " values (1, 'a real msg')"); conn.commit();
Paso 2: Reescribe las operaciones de actualización
A continuación, reescribe las operaciones de update
con el siguiente formato:
update msgs set msg = 'new message' where id = 1
Cambia las actualizaciones para que tengan el siguiente aspecto:
insert msgs_history (id, previous_msg, ts) values ((select id from msgs where id =1 ), (select msg from msgs where id = 1), PENDING_COMMIT_TIMESTAMP()); update msgs set msg = 'new message' where id = 1;
Este es el código Java:
// insert into historystmt.executeUpdate( "insert msgs_history (id, previous_msg, ts)" + " values ((select id from msgs where id =1)," + " (select msg from msgs where id = 1), PENDING_COMMIT_TIMESTAMP())"); // update into fact table stmt.executeUpdate("update msgs set msg = 'new message' where id = 1"); conn.commit();
Paso 3: Reescribe las operaciones de eliminación
Por último, reescribe las operaciones delete
del siguiente formulario:
delete from msgs where id = 1
Cambia las eliminaciones para que tengan el siguiente aspecto:
insert msgs_history (id, previous_msg, ts) values ((select id from msgs where id =1 ), (select msg from msgs where id = 1), PENDING_COMMIT_TIMESTAMP()); delete from msgs where id = 1;
Este es el código Java:
// insert into history stmt.executeUpdate( "insert msgs_history (id, previous_msg, ts)" + " values ((select id from msgs where id =1)," + " (select msg from msgs where id = 1), PENDING_COMMIT_TIMESTAMP()) "); // delete from real table stmt.executeUpdate("delete from msgs where id = 1"); conn.commit();
Usar la tabla del historial
Para acceder al historial de cambios, siga estos pasos:
select id,msg,current_timestamp() as ts from msgs where id = 1 union all select id,previous_msg, ts as msg from msgs_history where id = 1 order by ts desc
Los resultados deberían ser similares a los siguientes:
id msg ts 1 new message 2020-02-07T07:44:10.24833726Z 1 a real msg 2020-01-14T10:07:20.137935Z 1 2020-01-14T10:07:20.070374Z
Siguientes pasos
- Consulta más información sobre la función de marca de tiempo de confirmación de Spanner.
- Consulta más información sobre los streams de cambios de Spanner.
- Consulta arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Centro de arquitectura de Cloud.