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 dilakukannya perubahan pada kumpulan data di database Anda. Jika Anda memiliki database besar dengan banyak transaksi yang mengubah kumpulan data, dan Anda ingin melacak perubahan yang dilakukan pada set data tersebut, fitur stempel waktu commit akan memudahkan tugas ini.

Melalui serangkaian contoh kode, dokumen ini menunjukkan cara menulis ulang bahasa pengolahan data (DML) yang sudah ada untuk membuat log perubahan. Dokumen ini memperluas Menggunakan stempel waktu commit Cloud Spanner untuk membuat log perubahan dengan Go dengan mendemonstrasikan metodenya 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 ingin menyimpan kumpulan data di tabel msg_history secara serentak. Anda dapat menggunakan isi tabel histori nanti untuk penggunaan lain—misalnya, untuk audit atau sebagai sumber peristiwa.

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

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

Tabel msg_history berisi 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

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

Langkah 1: Menulis ulang operasi insert (penyisipan)

Langkah pertama adalah menulis ulang operasi insert dari format berikut:

insert into msgs (id, msg) values (1, 'a real msg')
  • Ubah penyisipan tersebut menjadi 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 adalah kode Java-nya:

    // 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: Menulis ulang operasi update (pembaruan)

Selanjutnya, Anda menulis ulang operasi update dari format berikut:

update msgs set msg = 'new message' where id = 1
  • Ubah pembaruan tersebut 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());
    update msgs set msg = 'new message' where id = 1;
    

    Berikut adalah kode Java-nya:

    // 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: Menulis ulang operasi delete (penghapusan)

Terakhir, Anda menulis ulang operasi delete dari format berikut:

delete from msgs where id = 1
  • Ubah penghapusan tersebut 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 adalah kode Java-nya:

    // 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 mirip 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