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

Penguncian predikat di PostgreSQL 9.2.1 dengan isolasi Serializable

Dari Isolasi Transaksi halaman:

Sebuah EXPLAIN pada SELECT itu dapat memberi tahu Anda apa rencana kueri yang diambil, tetapi jika tabelnya kecil (atau kosong!), PostgreSQL hampir pasti akan memilih pemindaian berurutan alih-alih merujuk indeks. Ini akan menyebabkan kunci predikat di seluruh tabel, menyebabkan kegagalan serialisasi setiap kali transaksi lain melakukan sesuatu pada tabel.

Di sistem saya:

isolation=# EXPLAIN SELECT * from mydevice where cid = 1;
                        QUERY PLAN                        
----------------------------------------------------------
 Seq Scan on mydevice  (cost=0.00..23.38 rows=5 width=46)
   Filter: (cid = 1)
(2 rows)

Anda dapat mencoba menambahkan indeks dan memaksanya untuk menggunakannya:

isolation=# CREATE INDEX mydevice_cid_key ON mydevice (cid);
CREATE INDEX
isolation=# SET enable_seqscan = off;
SET
isolation=# EXPLAIN SELECT * from mydevice where cid = 1;
                                    QUERY PLAN                                    
----------------------------------------------------------------------------------
 Index Scan using mydevice_cid_key on mydevice  (cost=0.00..8.27 rows=1 width=46)
   Index Cond: (cid = 1)
(2 rows)

Namun, ini bukan solusi yang tepat. Mari kita mundur sedikit.

Serializable dimaksudkan untuk menjamin bahwa transaksi akan memiliki efek yang persis sama seolah-olah dijalankan satu demi satu, terlepas dari kenyataan bahwa Anda benar-benar menjalankan transaksi ini secara bersamaan. PostgreSQL tidak memiliki sumber daya tak terbatas, jadi memang benar bahwa PostgreSQL menempatkan kunci predikat pada data yang benar-benar diakses oleh kueri Anda, "data" dapat berarti lebih dari sekadar "baris yang dikembalikan".

PostgreSQL memilih untuk menandai kegagalan serialisasi ketika dianggap ada masalah, bukan saat sudah pasti. (Oleh karena itu cara menggeneralisasi kunci baris ke kunci halaman.) Pilihan desain ini menyebabkan kesalahan positif, seperti yang ada dalam contoh Anda. Positif palsu kurang dari ideal, namun tidak memengaruhi kebenaran semantik isolasi.

Pesan kesalahannya adalah:

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.

Petunjuk itu adalah kuncinya. Aplikasi Anda perlu menangkap kegagalan serialisasi dan mencoba ulang seluruh operasi . Ini benar setiap kali SERIALIZABLE sedang dimainkan -- ia menjamin kebenaran serial meskipun ada konkurensi, tetapi ia tidak dapat melakukannya tanpa bantuan aplikasi Anda. Dengan kata lain, jika Anda benar-benar melakukan modifikasi bersamaan, satu-satunya cara PostgreSQL dapat memenuhi persyaratan isolasi adalah dengan meminta aplikasi Anda untuk membuat serial sendiri. Jadi:



  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 menghitung waktu antara dua cap waktu (PostgreSQL)

  2. Susunan yang lebih kuat dengan dukungan ICU di PostgreSQL 10

  3. Bagaimana cara menjumlahkan nilai dalam array JSONB di Postgresql?

  4. Memeriksa keberadaan indeks di PostgreSQL

  5. Kapan kueri (PILIH) direncanakan?