Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Apakah SELECT FOR UPDATE mencegah koneksi lain dimasukkan saat baris tidak ada?

MySQL

PILIH ... UNTUK PEMBARUAN dengan PEMBARUAN

Menggunakan transaksi dengan InnoDB (komit otomatis dimatikan), SELECT ... FOR UPDATE memungkinkan satu sesi untuk sementara mengunci catatan tertentu (atau catatan) sehingga tidak ada sesi lain yang dapat memperbaruinya. Kemudian, dalam transaksi yang sama, sesi tersebut benar-benar dapat melakukan UPDATE pada catatan yang sama dan melakukan atau memutar kembali transaksi. Ini akan memungkinkan Anda untuk mengunci catatan sehingga tidak ada sesi lain yang dapat memperbaruinya sementara Anda mungkin melakukan logika bisnis lain.

Ini dilakukan dengan penguncian. InnoDB menggunakan indeks untuk mengunci catatan, jadi mengunci catatan yang ada tampaknya mudah--cukup mengunci indeks untuk catatan itu.

PILIH ... UNTUK PEMBARUAN dengan INSERT

Namun, untuk menggunakan SELECT ... FOR UPDATE dengan INSERT , bagaimana Anda mengunci indeks untuk catatan yang belum ada? Jika Anda menggunakan tingkat isolasi default REPEATABLE READ , InnoDB juga akan memanfaatkan celah kunci. Asalkan Anda mengetahui id (atau bahkan rentang id) untuk dikunci, maka InnoDB dapat mengunci celah tersebut sehingga tidak ada catatan lain yang dapat dimasukkan ke dalam celah itu sampai kita selesai melakukannya.

Jika id . Anda kolom adalah kolom kenaikan otomatis, lalu SELECT ... FOR UPDATE dengan INSERT INTO akan bermasalah karena Anda tidak akan tahu apa id yang baru adalah sampai Anda memasukkannya. Namun, karena Anda tahu id yang ingin Anda masukkan, SELECT ... FOR UPDATE dengan INSERT akan berhasil.

PERINGATAN

Pada tingkat isolasi default, SELECT ... FOR UPDATE pada catatan yang tidak ada tidak memblokir transaksi lainnya. Jadi, jika dua transaksi keduanya melakukan SELECT ... FOR UPDATE pada catatan indeks yang tidak ada yang sama, keduanya akan mendapatkan kunci, dan tidak ada transaksi yang dapat memperbarui catatan. Bahkan, jika mereka mencoba, kebuntuan akan terdeteksi.

Oleh karena itu, jika Anda tidak ingin menghadapi kebuntuan, Anda dapat melakukan hal berikut:

MASUKKAN KE ...

Mulai transaksi, dan lakukan INSERT . Lakukan logika bisnis Anda, dan lakukan atau batalkan transaksi. Segera setelah Anda melakukan INSERT pada indeks catatan yang tidak ada pada transaksi pertama, semua transaksi lainnya akan diblokir jika mereka mencoba untuk INSERT record dengan indeks unik yang sama. Jika transaksi kedua mencoba memasukkan catatan dengan indeks yang sama setelah transaksi pertama melakukan penyisipan, maka itu akan mendapatkan kesalahan "kunci duplikat". Tangani sebagaimana mestinya.

PILIH ... KUNCI DALAM MODE BERBAGI

Jika Anda memilih dengan LOCK IN SHARE MODE sebelum INSERT , jika transaksi sebelumnya telah memasukkan record tersebut tetapi belum melakukan commit, SELECT ... LOCK IN SHARE MODE akan memblokir hingga transaksi sebelumnya selesai.

Jadi untuk mengurangi kemungkinan kesalahan kunci duplikat, terutama jika Anda menahan kunci beberapa saat saat menjalankan logika bisnis sebelum melakukan atau memutarnya kembali:

  1. SELECT bar FROM FooBar WHERE foo = ? LOCK FOR UPDATE
  2. Jika tidak ada catatan yang dikembalikan, maka
  3. INSERT INTO FooBar (foo, bar) VALUES (?, ?)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mengapa pembaruan massal templat hibernasi ini tidak berfungsi

  2. Atur Ulang Urutan di oracle 11g

  3. Oracle SQL - Jumlahkan dan kelompokkan data berdasarkan minggu

  4. Cara Menemukan Nama Batasan di Oracle

  5. format interval dengan to_char