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

org.postgresql.util.PSQLException:ERROR:tidak dapat membuat serial akses karena dependensi baca/tulis di antara transaksi

Kapan pun Anda meminta SERIALIZABLE isolasi DB akan mencoba membuat kumpulan kueri yang bersamaan tampak telah dieksekusi secara serial dalam hal hasil yang mereka hasilkan. Ini tidak selalu memungkinkan, mis. ketika dua transaksi memiliki ketergantungan timbal balik. Dalam hal ini, PostgreSQL akan membatalkan salah satu transaksi dengan kesalahan kegagalan serialisasi, memberi tahu Anda bahwa Anda harus mencobanya lagi.

Kode yang menggunakan SERIALIZABLE harus selalu siap untuk mencoba kembali transaksi. Itu harus memeriksa SQLSTATE dan, untuk kegagalan serialisasi, ulangi transaksi.

Lihat dokumentasi isolasi transaksi .

Dalam hal ini, saya pikir kesalahpahaman utama Anda mungkin adalah:

karena tidak seperti itu, ini adalah INSERT ... SELECT yang menyentuh vo_business.repositoryoperation baik untuk membaca maupun menulis. Itu cukup untuk menciptakan ketergantungan potensial dengan transaksi lain yang melakukan hal yang sama, atau transaksi yang membaca dan menulis ke tabel dengan cara lain.

Selain itu, kode isolasi yang dapat diserialisasi dalam beberapa keadaan dapat berubah menjadi penyimpanan informasi ketergantungan tingkat blok untuk alasan efisiensi. Jadi mungkin tidak selalu transaksi menyentuh baris yang sama, hanya blok penyimpanan yang sama, terutama di bawah beban.

PostgreSQL akan lebih memilih untuk membatalkan transaksi serial jika tidak yakin itu aman. Sistem pembuktian memiliki keterbatasan. Jadi, mungkin juga Anda baru saja menemukan kasus yang membodohinya.

Untuk mengetahui dengan pasti saya perlu melihat kedua transaksi secara berdampingan, tetapi berikut adalah bukti yang menunjukkan insert ... select dapat bertentangan dengan dirinya sendiri. Buka tiga psql sesi dan jalankan:

session0: CREATE TABLE serialdemo(x integer, y integer);

session0: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session0: LOCK TABLE serialdemo IN ACCESS EXCLUSIVE MODE;

session1: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session2: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session1: INSERT INTO serialdemo (x, y)
          SELECT 1, 2
          WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);

session2: INSERT INTO serialdemo (x, y)
          SELECT 1, 2
          WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);

session0: ROLLBACK;

session1: COMMIT;

session2: COMMIT;

session1 akan melakukan dengan baik. session2 akan gagal dengan:

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.

Ini bukan kegagalan serialisasi yang sama dengan kasus Anda, dan tidak membuktikan bahwa Anda pernyataan dapat bertentangan satu sama lain, tetapi ini menunjukkan bahwa insert ... select tidak atomik seperti yang Anda pikirkan.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara melemparkan byte tipe ke presisi ganda

  2. Query SQL untuk mendapatkan daftar hierarki supervisor. karyawan --> supervisor --> supervisor

  3. menggunakan profil boot musim semi dengan atribut konteks liquibase changeset untuk mengelola ruang lingkup changset

  4. heroku run rake db:kesalahan migrasi

  5. Cara memasukkan daftar python ke tabel Postgres