PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Tingkat isolasi SERIALIZABLE di Spring-JDBC

TL;DR:Deteksi konflik serializability meningkat secara dramatis di Hal 9.1, jadi tingkatkan.

Sulit untuk mengetahui dari deskripsi Anda apa sebenarnya SQL itu dan mengapa Anda berharap mendapatkan rollback. Sepertinya Anda benar-benar salah memahami isolasi serializable, mungkin berpikir itu menguji semua predikat dengan sempurna, padahal tidak, terutama tidak di Hal 8.4.

SERIALIZABLE tidak sepenuhnya menjamin bahwa transaksi dijalankan seolah-olah dijalankan secara seri - karena melakukan hal itu akan sangat mahal dari sudut pandang kinerja jika memungkinkan. Ini hanya menyediakan pemeriksaan terbatas. Apa yang diperiksa dan bagaimana variasi dari database ke database dan versi ke versi, jadi Anda perlu membaca dokumen untuk versi database Anda.

Anomali mungkin terjadi, di mana dua transaksi dieksekusi dalam SERIALIZABLE mode menghasilkan hasil yang berbeda jika transaksi tersebut benar-benar dijalankan secara seri.

Baca dokumentasi tentang isolasi transaksi di Hal. untuk mempelajari lebih lanjut. Perhatikan bahwa SERIALIZABLE perilaku berubah secara dramatis di Pg 9.1, jadi pastikan untuk membaca versi manual yang sesuai untuk versi Pg Anda. Ini versi 8.4 . Secara khusus baca 13.2.2.1. Isolasi Serializable versus Serializability Sejati . Sekarang bandingkan dengan dukungan serialisasi berbasis penguncian predikat yang sangat ditingkatkan dijelaskan dalam Hal 9.1 dokumen .

Sepertinya Anda mencoba menjalankan logika seperti kodesemu ini:

count = query("SELECT count(*) FROM the_table");
if (count < threshold):
    query("INSERT INTO the_table (...) VALUES (...)");

Jika demikian, itu tidak akan berfungsi di Hal 8.4 saat dijalankan secara bersamaan - itu hampir sama dengan contoh anomali yang digunakan dalam dokumentasi yang ditautkan di atas. Hebatnya itu benar-benar berfungsi pada Hal 9.1; Saya tidak menyangka bahkan penguncian predikat 9.1 akan menangkap penggunaan agregat.

Anda menulis bahwa:

tetapi 8.4 tidak akan mendeteksi bahwa kedua transaksi tersebut saling bergantung, sesuatu yang sepele dapat Anda buktikan dengan menggunakan dua psql sesi untuk mengujinya. Hanya dengan hal-hal yang benar-serializability yang diperkenalkan di 9.1 ini akan berhasil - dan sejujurnya, saya terkejut itu bekerja di 9.1.

Jika Anda ingin melakukan sesuatu seperti memberlakukan jumlah baris maksimum di Hal 8.4, Anda perlu LOCK meja untuk mencegah INSERT concurrent s, melakukan penguncian baik secara manual atau melalui fungsi pemicu . Melakukannya di pemicu secara inheren akan membutuhkan promosi kunci dan dengan demikian akan sering menemui jalan buntu, tetapi akan berhasil melakukan pekerjaan itu. Lebih baik dilakukan di aplikasi tempat Anda dapat mengeluarkan LOCK TABLE my_table IN EXCLUSIVE MODE bahkan sebelum mendapatkan SELECT ing dari tabel, sehingga sudah memiliki mode kunci tertinggi yang dibutuhkan di atas meja dan dengan demikian tidak perlu promosi kunci rawan kebuntuan. EXCLUSIVE mode kunci sesuai karena memungkinkan SELECT s tapi tidak ada yang lain.

Berikut cara mengujinya dalam dua sesi psql:

SESSION 1                               SESSION 2

create table ser_test( x text );

BEGIN TRANSACTION 
ISOLATION LEVEL SERIALIZABLE;


                                        BEGIN TRANSACTION 
                                        ISOLATION LEVEL SERIALIZABLE;

SELECT count(*) FROM ser_test ;

                                        SELECT count(*) FROM ser_test ;

INSERT INTO ser_test(x) VALUES ('bob');


                                        INSERT INTO ser_test(x) VALUES ('bob');

 COMMIT;

                                        COMMIT;

Saat dijalankan pada Hal 9.1, komit st commits succeeds then the second COMMIT` gagal dengan:

regress=# COMMIT;
ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.

tetapi ketika dijalankan pada 8.4 kedua komit berhasil, karena 8.4 tidak memiliki semua kode penguncian predikat untuk serializability yang ditambahkan di 9.1.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. postgresql:tipe data untuk intisari pesan md5?

  2. Aplikasi Rails di Heroku Tidak Dapat Menulis ke Database PostgreSQL, Hanya Membaca

  3. mendapatkan id dari beberapa baris yang dimasukkan ke dalam psycopg2

  4. psql:FATAL:basis data <pengguna> tidak ada

  5. Cara mengubah bidang id penomoran otomatis ke tipe serial di PostgreSQL