Isolasi yang dapat diserialisasi - Amazon Redshift

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Isolasi yang dapat diserialisasi

Beberapa aplikasi tidak hanya memerlukan kueri dan pemuatan bersamaan, tetapi juga kemampuan untuk menulis ke beberapa tabel atau tabel yang sama secara bersamaan. Dalam konteks ini, secara bersamaan berarti tumpang tindih, tidak dijadwalkan untuk berjalan pada waktu yang bersamaan. Dua transaksi dianggap bersamaan jika yang kedua dimulai sebelum komitmen pertama. Operasi bersamaan dapat berasal dari sesi berbeda yang dikendalikan baik oleh pengguna yang sama atau oleh pengguna yang berbeda.

catatan

Amazon Redshift mendukung perilaku komit otomatis default di mana setiap SQL perintah yang dijalankan secara terpisah melakukan komit satu per satu. Jika Anda melampirkan satu set perintah dalam blok transaksi (didefinisikan oleh BEGIN dan END pernyataan), blok tersebut melakukan sebagai satu transaksi, sehingga Anda dapat memutar kembali jika perlu. Pengecualian untuk perilaku ini adalah VACUUM perintah TRUNCATE and, yang secara otomatis melakukan semua perubahan beredar yang dibuat dalam transaksi saat ini.

Beberapa SQL klien mengeluarkan BEGIN dan COMMIT memerintahkan secara otomatis, sehingga klien mengontrol apakah sekelompok pernyataan dijalankan sebagai transaksi atau setiap pernyataan individu dijalankan sebagai transaksinya sendiri. Periksa dokumentasi untuk antarmuka yang Anda gunakan. Misalnya, saat menggunakan JDBC driver Amazon Redshift, a JDBC PreparedStatement dengan string kueri yang berisi beberapa SQL perintah (koma dipisahkan) menjalankan semua pernyataan sebagai satu transaksi. Sebaliknya, jika Anda menggunakan SQL Workbench/J dan set AUTO COMMIT ON, maka jika Anda menjalankan beberapa pernyataan, setiap pernyataan berjalan sebagai transaksinya sendiri.

Operasi penulisan bersamaan didukung di Amazon Redshift dengan cara protektif, menggunakan kunci tulis pada tabel dan prinsip isolasi serial. Isolasi serializable mempertahankan ilusi bahwa transaksi yang berjalan melawan tabel adalah satu-satunya transaksi yang berjalan melawan tabel itu. Misalnya, dua transaksi yang berjalan secara bersamaan, T1 dan T2, harus menghasilkan hasil yang sama dengan setidaknya salah satu dari berikut ini:

  • T1 dan T2 berjalan secara serial dalam urutan itu.

  • T2 dan T1 berjalan secara serial dalam urutan itu.

Transaksi bersamaan tidak terlihat satu sama lain; mereka tidak dapat mendeteksi perubahan satu sama lain. Setiap transaksi bersamaan akan membuat snapshot database di awal transaksi. Snapshot database dibuat dalam transaksi pada kemunculan pertama sebagian besar SELECT pernyataan, DML perintah sepertiCOPY,,DELETE,INSERT, dan UPDATETRUNCATE, dan DDL perintah berikut:

  • ALTERTABLE(untuk menambah atau menjatuhkan kolom)

  • CREATE TABLE

  • DROP TABLE

  • TRUNCATE TABLE

Jika ada eksekusi serial dari transaksi bersamaan menghasilkan hasil yang sama dengan eksekusi bersamaan mereka, transaksi tersebut dianggap “serializable” dan dapat dijalankan dengan aman. Jika tidak ada eksekusi serial dari transaksi tersebut yang dapat menghasilkan hasil yang sama, transaksi yang menjalankan pernyataan yang mungkin merusak kemampuan untuk membuat serial dihentikan dan dibatalkan.

Tabel katalog sistem (PG) dan tabel sistem Amazon Redshift lainnya (STLdanSTV) tidak terkunci dalam transaksi. Oleh karena itu, perubahan pada objek database yang muncul dari DDL dan TRUNCATE operasi terlihat pada komit untuk setiap transaksi bersamaan.

Misalnya, anggaplah tabel A ada dalam database ketika dua transaksi bersamaan, T1 dan T2, dimulai. Misalkan T2 mengembalikan daftar tabel dengan memilih dari tabel katalog PG_TABLES. Kemudian T1 menjatuhkan tabel A dan komit, lalu T2 mencantumkan tabel lagi. Tabel A sekarang tidak lagi terdaftar. Jika T2 mencoba menanyakan tabel yang dijatuhkan, Amazon Redshift mengembalikan kesalahan “relasi tidak ada”. Kueri katalog yang mengembalikan daftar tabel ke T2 atau memeriksa bahwa tabel A ada tidak tunduk pada aturan isolasi yang sama seperti operasi yang dilakukan pada tabel pengguna.

Transaksi untuk pembaruan tabel ini berjalan dalam mode isolasi komited baca. Tabel katalog awalan PG tidak mendukung isolasi snapshot.

Isolasi serializable untuk tabel sistem dan tabel katalog

Snapshot database juga dibuat dalam transaksi untuk SELECT kueri apa pun yang mereferensikan tabel yang dibuat pengguna atau tabel sistem Amazon Redshift (atau). STL STV SELECTkueri yang tidak mereferensikan tabel apa pun tidak membuat snapshot database transaksi baru. INSERT,DELETE, dan UPDATE pernyataan yang hanya beroperasi pada tabel katalog sistem (PG) juga tidak membuat snapshot database transaksi baru.

Cara memperbaiki kesalahan isolasi serial

ERROR:1023DETAIL: Pelanggaran isolasi serial di atas meja di Redshift

Saat Amazon Redshift mendeteksi kesalahan isolasi yang dapat diserialisasi, Anda akan melihat pesan kesalahan seperti berikut ini.

ERROR:1023 DETAIL: Serializable isolation violation on table in Redshift

Untuk mengatasi kesalahan isolasi serializable, Anda dapat mencoba metode berikut:

  • Coba lagi transaksi yang dibatalkan.

    Amazon Redshift mendeteksi bahwa beban kerja bersamaan tidak dapat diserialkan. Ini menunjukkan celah dalam logika aplikasi, yang biasanya dapat diatasi dengan mencoba kembali transaksi yang mengalami kesalahan. Jika masalah berlanjut, coba salah satu metode lain.

  • Pindahkan operasi apa pun yang tidak harus berada dalam transaksi atom yang sama di luar transaksi.

    Metode ini berlaku ketika operasi individu dalam dua transaksi saling mereferensikan satu sama lain dengan cara yang dapat mempengaruhi hasil transaksi lainnya. Misalnya, dua sesi berikut masing-masing memulai transaksi.

    Session1_Redshift=# begin;
    Session2_Redshift=# begin;

    Hasil dari SELECT pernyataan dalam setiap transaksi mungkin dipengaruhi oleh INSERT pernyataan di yang lain. Dengan kata lain, anggaplah Anda menjalankan pernyataan berikut secara serial, dalam urutan apa pun. Dalam setiap kasus, hasilnya adalah salah satu SELECT pernyataan yang mengembalikan satu baris lebih banyak daripada jika transaksi dijalankan secara bersamaan. Tidak ada urutan di mana operasi dapat berjalan secara serial yang menghasilkan hasil yang sama seperti ketika dijalankan secara bersamaan. Dengan demikian, operasi terakhir yang dijalankan menghasilkan kesalahan isolasi serial.

    Session1_Redshift=# select * from tab1; Session1_Redshift=# insert into tab2 values (1);
    Session2_Redshift=# insert into tab1 values (1); Session2_Redshift=# select * from tab2;

    Dalam banyak kasus, hasil SELECT pernyataan tidak penting. Dengan kata lain, atomisitas operasi dalam transaksi tidak penting. Dalam kasus ini, pindahkan SELECT pernyataan di luar transaksi mereka, seperti yang ditunjukkan pada contoh berikut.

    Session1_Redshift=# begin; Session1_Redshift=# insert into tab1 values (1) Session1_Redshift=# end; Session1_Redshift=# select * from tab2;
    Session2_Redshift # select * from tab1; Session2_Redshift=# begin; Session2_Redshift=# insert into tab2 values (1) Session2_Redshift=# end;

    Dalam contoh ini, tidak ada referensi silang dalam transaksi. Kedua INSERT pernyataan tersebut tidak saling mempengaruhi. Dalam contoh ini, setidaknya ada satu urutan di mana transaksi dapat berjalan secara serial dan menghasilkan hasil yang sama seolah-olah dijalankan secara bersamaan. Ini berarti bahwa transaksi dapat diserialkan.

  • Paksa serialisasi dengan mengunci semua tabel di setiap sesi.

    LOCKPerintah memblokir operasi yang dapat mengakibatkan kesalahan isolasi serial. Saat Anda menggunakan LOCK perintah, pastikan untuk melakukan hal berikut:

    • Kunci semua tabel yang terpengaruh oleh transaksi, termasuk yang terpengaruh oleh SELECT pernyataan hanya-baca di dalam transaksi.

    • Kunci tabel dalam urutan yang sama, terlepas dari urutan operasi yang dilakukan.

    • Kunci semua tabel di awal transaksi, sebelum melakukan operasi apa pun.

  • Gunakan isolasi snapshot untuk transaksi bersamaan

    Gunakan ALTER DATABASE perintah dengan isolasi snapshot. Untuk informasi selengkapnya tentang SNAPSHOT parameter untuk ALTERDATABASE, lihatParameter.

ERROR:1018DETAIL: Hubungan tidak ada

Saat menjalankan operasi Amazon Redshift bersamaan di sesi yang berbeda, Anda akan melihat pesan galat seperti berikut ini.

ERROR: 1018 DETAIL: Relation does not exist.

Transaksi di Amazon Redshift mengikuti isolasi snapshot. Setelah transaksi dimulai, Amazon Redshift mengambil snapshot dari database. Untuk seluruh siklus hidup transaksi, transaksi beroperasi pada status database sebagaimana tercermin dalam snapshot. Jika transaksi membaca dari tabel yang tidak ada dalam snapshot, itu akan menampilkan pesan kesalahan 1018 yang ditunjukkan sebelumnya. Bahkan ketika transaksi bersamaan lainnya membuat tabel setelah transaksi mengambil snapshot, transaksi tidak dapat membaca dari tabel yang baru dibuat.

Untuk mengatasi kesalahan isolasi serialisasi ini, Anda dapat mencoba memindahkan awal transaksi ke titik di mana Anda tahu tabel itu ada.

Jika tabel dibuat oleh transaksi lain, poin ini setidaknya setelah transaksi dilakukan. Juga, pastikan bahwa tidak ada transaksi bersamaan yang telah dilakukan yang mungkin telah menjatuhkan tabel.

session1 = # BEGIN; session1 = # DROP TABLE A; session1 = # COMMIT;
session2 = # BEGIN;
session3 = # BEGIN; session3 = # CREATE TABLE A (id INT); session3 = # COMMIT;
session2 = # SELECT * FROM A;

Operasi terakhir yang dijalankan sebagai operasi baca oleh session2 menghasilkan kesalahan isolasi serial. Kesalahan ini terjadi ketika session2 mengambil snapshot dan tabel telah dihapus oleh sesi komitmen1. Dengan kata lain, meskipun session3 bersamaan telah membuat tabel, session2 tidak melihat tabel karena tidak ada dalam snapshot.

Untuk mengatasi kesalahan ini, Anda dapat menyusun ulang sesi sebagai berikut.

session1 = # BEGIN; session1 = # DROP TABLE A; session1 = # COMMIT;
session3 = # BEGIN; session3 = # CREATE TABLE A (id INT); session3 = # COMMIT;
session2 = # BEGIN; session2 = # SELECT * FROM A;

Sekarang ketika session2 mengambil snapshot-nya, session3 telah dilakukan, dan tabelnya ada di database. Session2 dapat membaca dari tabel tanpa kesalahan.