本文將說明如何使用提交時間戳記功能,追蹤資料庫記錄的變更日期和時間。如果您有大型資料庫,其中包含許多變更記錄的交易,且您想擷取對資料集所做的變更,則可以使用提交時間戳記功能簡化這項工作。
本文件將透過一系列程式碼範例,說明如何重寫現有的資料操縱語言 (DML),以建立變更記錄。本文件延伸自「使用 Cloud Spanner 修訂時間戳記,利用 Go 建立變更記錄」,示範使用 Java 和 JDBC 的方法。邏輯以 SQL 表示,而非 Spanner 用戶端物件。
表格的運作方式
假設您有名為 msgs
的事實資料表和名為 msg_history
的歷史資料表。每次修改事實資料表時,您都想同時在 msg_history
資料表中儲存記錄。您之後可以將記錄表的內容用於其他用途,例如稽核或做為事件來源。
msgs
資料表會保留事實,以交易 ID (id
) 和訊息 (msg
) 表示。您用來建立資料表的資料定義語言 (DDL) 陳述式如下所示:
CREATE TABLE msgs (
id INT64,
msg STRING(MAX),
) PRIMARY KEY (id)
msg_history
資料表會保存交易記錄。下列 DDL 會建立記錄表。資料欄 ts
會儲存修訂時間戳記。
CREATE TABLE msgs_history (
id INT64,
ts TIMESTAMP OPTIONS (allow_commit_timestamp=true),
previous_msg STRING(MAX)
) PRIMARY KEY (ts, id)
示例
您必須在相同的交易中對歷史資料表執行作業,而非只寫入資料表。Spanner 的 JDBC 驅動程式可支援交易的開始和結束宣告,這是標準的 JDBC 作業。
步驟 1:重寫插入作業
第一步是使用下列表單重寫 insert
作業:
insert into msgs (id, msg) values (1, 'a real msg')
將插入內容變更為以下內容:
insert into msgs_history (id, previous_msg, ts) values (1, Null, PENDING_COMMIT_TIMESTAMP()); insert into msgs (id, msg) values (1, 'a real msg');
以下是 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();
步驟 2:重寫更新作業
接下來,您要使用下列表單重寫 update
運算:
update msgs set msg = 'new message' where id = 1
將更新內容變更為下列內容:
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;
以下是 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();
步驟 3:重寫刪除作業
最後,您可以使用下列表單重寫 delete
作業:
delete from msgs where id = 1
將刪除項目變更為下列內容:
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;
以下是 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();
使用記錄資料表
如要查看變更記錄,請按照下列步驟操作:
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
結果如下所示:
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
後續步驟
- 進一步瞭解 Spanner 提交時間戳記功能。
- 進一步瞭解 Spanner 變更串流。
- 探索 Google Cloud 的參考架構、圖表和最佳做法。歡迎瀏覽我們的雲端架構中心。