Membuat log perubahan dengan JDBC menggunakan fitur stempel waktu commit Spanner

Dokumen ini menjelaskan cara menggunakan fitur stempel waktu commit untuk melacak tanggal dan waktu ketika perubahan dilakukan pada kumpulan data database. Jika Anda memiliki database besar dengan banyak transaksi yang mengubah record, dan Anda ingin mencatat perubahan yang dilakukan pada set data, fitur stempel waktu commit akan menyederhanakan tugas ini.

Melalui serangkaian contoh kode, dokumen ini menunjukkan cara menulis ulang bahasa pengolahan data (DML) yang ada untuk membuat log perubahan. Dokumen ini memperluas Menggunakan stempel waktu commit Cloud Spanner untuk membuat log perubahan dengan Go dengan mendemonstrasikan metode menggunakan Java dan JDBC. Logika ini direpresentasikan dalam SQL, bukan sebagai objek klien Spanner.

Cara kerja tabel

Asumsikan Anda memiliki tabel fakta bernama msgs dan tabel histori bernama msg_history. Setiap kali tabel fakta diubah, Anda perlu menyimpan data dalam tabel msg_history secara serentak Anda dapat menggunakan konten tabel histori nanti untuk penggunaan lain—misalnya, untuk audit atau sebagai sumber peristiwa.

Tabel msgs menyimpan fakta, yang diwakili oleh ID transaksi (id) dan pesan (msg). Pernyataan bahasa definisi data (DDL) yang Anda gunakan untuk membuat tabel dapat terlihat seperti berikut:

CREATE TABLE msgs (
    id INT64,
    msg STRING(MAX),
) PRIMARY KEY (id)

Tabel msg_history menyimpan histori transaksi. DDL berikut akan membuat tabel histori. Kolom ts menyimpan stempel waktu commit.

CREATE TABLE msgs_history (
    id INT64,
    ts TIMESTAMP OPTIONS (allow_commit_timestamp=true),
    previous_msg STRING(MAX)
) PRIMARY KEY (ts, id)

Contoh

Daripada hanya menulis ke tabel fakta, Anda harus melakukan operasi ke tabel histori dalam transaksi yang sama. Driver JDBC Spanner mendukung deklarasi awal dan akhir transaksi, yang merupakan operasi JDBC standar.

Langkah 1: Tulis ulang operasi penyisipan

Langkah pertama adalah menulis ulang operasi insert dari bentuk berikut:

insert into msgs (id, msg) values (1, 'a real msg')
  • Ubah penyisipan agar terlihat seperti berikut:

    insert into msgs_history (id, previous_msg, ts) values (1, Null, PENDING_COMMIT_TIMESTAMP());
    insert into msgs (id, msg) values (1, 'a real msg');
    

    Berikut ini kode Javanya:

    // 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();
    

Langkah 2: Tulis ulang operasi update

Selanjutnya, Anda menulis ulang operasi update dari bentuk berikut:

update msgs set msg = 'new message' where id = 1
  • Ubah update agar terlihat seperti berikut:

    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;
    

    Berikut ini kode Javanya:

    // 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();
    

Langkah 3: Tulis ulang operasi hapus

Terakhir, Anda menulis ulang operasi delete dari bentuk berikut:

delete from msgs where id = 1
  • Ubah penghapusan menjadi seperti berikut:

    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;
    

    Berikut ini kode Javanya:

    // 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();
    

Menggunakan tabel histori

  • Akses histori perubahan sebagai berikut:

    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
    

    Hasilnya akan terlihat seperti berikut:

    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
    

Langkah berikutnya