insertintomsgs_history(id,previous_msg,ts)values(1,Null,PENDING_COMMIT_TIMESTAMP());insertintomsgs(id,msg)values(1,'a real msg');
以下是 Java 程式碼:
// insert into historystmt.executeUpdate("insert into msgs_history (id, previous_msg, ts)"+" values (1, Null, PENDING_COMMIT_TIMESTAMP())");// insert into real tablestmt.executeUpdate("insert into msgs (id, msg)"+" values (1, 'a real msg')");conn.commit();
// 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 tablestmt.executeUpdate("update msgs set msg = 'new message' where id = 1");conn.commit();
// 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()) ");// delete from real tablestmt.executeUpdate("delete from msgs where id = 1");conn.commit();
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["難以理解","hardToUnderstand","thumb-down"],["資訊或程式碼範例有誤","incorrectInformationOrSampleCode","thumb-down"],["缺少我需要的資訊/範例","missingTheInformationSamplesINeed","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-09-05 (世界標準時間)。"],[],[],null,["# Create a change log with JDBC using the Spanner commit timestamp feature\n\nThis document describes how to use the\n[commit timestamp feature](/spanner/docs/commit-timestamp)\nto track the date and time when changes are made to your database records. When\nyou have a large database with many transactions that change records and you\nwant to capture changes made to the datasets, the commit timestamp feature\nsimplifies this task.\n\nThrough a series of code samples, this document shows you how to rewrite\nexisting data manipulation language (DML) to create a change log. The document\nextends [Using Cloud Spanner commit timestamps to create a change log with Go](/community/tutorials/cloud-spanner-commit-timestamp-change-log)\nby demonstrating the methods using Java and JDBC. The logic is represented in\nSQL rather than as Spanner client objects.\n| **Note:** An alternative to the solutions proposed on this page is Spanner change streams. Spanner change streams watch and stream out a Spanner database's data changes to other services. For more information, see [About change streams](/spanner/docs/change-streams).\n\nHow the tables work\n-------------------\n\nAssume you have a facts table called `msgs` and a history table called\n`msg_history`. Each time the facts table gets modified, you want to concurrently\nsave a record in the `msg_history` table. You can use the contents of the\nhistory table later for other uses---for example, for auditing or as an event\nsource.\n\nThe `msgs` table holds the facts, represented by a transaction ID (`id`) and\nthe message (`msg`). The data definition language (DDL) statement that you use\nto create the table looks like the following: \n\n CREATE TABLE msgs (\n id INT64,\n msg STRING(MAX),\n ) PRIMARY KEY (id)\n\nThe `msg_history` table holds the transaction history. The following DDL\ncreates the history table. The column `ts` stores the commit timestamp. \n\n CREATE TABLE msgs_history (\n id INT64,\n ts TIMESTAMP OPTIONS (allow_commit_timestamp=true),\n previous_msg STRING(MAX)\n ) PRIMARY KEY (ts, id)\n\n### The examples\n\nInstead of writing only to the facts table, you must do the operation to the\nhistory table in the same transaction. Spanner's JDBC driver\nsupports declaration of the start and end of a transaction, which is a standard\nJDBC operation.\n\n#### Step 1: Rewrite the insert operations\n\nThe first step is to rewrite the `insert` operations from the following form: \n\n insert into msgs (id, msg) values (1, 'a real msg')\n\n- Change the inserts to look like the following:\n\n insert into msgs_history (id, previous_msg, ts) values (1, Null, PENDING_COMMIT_TIMESTAMP());\n insert into msgs (id, msg) values (1, 'a real msg');\n\n Here's the Java code: \n\n // insert into history\n stmt.executeUpdate(\n \"insert into msgs_history (id, previous_msg, ts)\"\n + \" values (1, Null, PENDING_COMMIT_TIMESTAMP())\");\n // insert into real table\n stmt.executeUpdate(\"insert into msgs (id, msg)\" + \" values (1, 'a real msg')\");\n conn.commit();\n\n#### Step 2: Rewrite the update operations\n\nNext, you rewrite the `update` operations from the following form: \n\n update msgs set msg = 'new message' where id = 1\n\n- Change the updates to look like the following:\n\n 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());\n update msgs set msg = 'new message' where id = 1;\n\n Here's the Java code: \n\n // insert into historystmt.executeUpdate(\n \"insert msgs_history (id, previous_msg, ts)\"\n + \" values ((select id from msgs where id =1),\"\n + \" (select msg from msgs where id = 1), PENDING_COMMIT_TIMESTAMP())\");\n // update into fact table\n stmt.executeUpdate(\"update msgs set msg = 'new message' where id = 1\");\n conn.commit();\n\n#### Step 3: Rewrite the delete operations\n\nFinally, you rewrite the `delete` operations from the following form: \n\n delete from msgs where id = 1\n\n- Change the deletes to look like the following:\n\n 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());\n delete from msgs where id = 1;\n\n Here's the Java code: \n\n // insert into history\n stmt.executeUpdate(\n \"insert msgs_history (id, previous_msg, ts)\"\n + \" values ((select id from msgs where id =1),\"\n + \" (select msg from msgs where id = 1), PENDING_COMMIT_TIMESTAMP()) \");\n // delete from real table\n stmt.executeUpdate(\"delete from msgs where id = 1\");\n conn.commit();\n\n### Using the history table\n\n- Access the change history as follows:\n\n select id,msg,current_timestamp() as ts\n from msgs where id = 1\n union all\n select id,previous_msg, ts as msg\n from msgs_history where id = 1 order by ts desc\n\n The results look similar to the following: \n\n ```\n id msg ts\n 1 new message 2020-02-07T07:44:10.24833726Z\n 1 a real msg 2020-01-14T10:07:20.137935Z\n 1 2020-01-14T10:07:20.070374Z\n ```\n\nWhat's next\n-----------\n\n- Read more about the [Spanner commit timestamp feature](/spanner/docs/commit-timestamp).\n- Learn more about [Spanner change streams](/spanner/docs/change-streams).\n- Explore reference architectures, diagrams, and best practices about Google Cloud. Take a look at our [Cloud Architecture Center](/architecture)."]]