Satu-satunya cara portabel untuk mencapai konsistensi antara ruang dan tag dan memastikan ruang tidak pernah dikembalikan setelah dihapus adalah menguncinya dengan SELECT FOR UPDATE
.
Namun dalam beberapa sistem penguncian adalah efek samping dari kontrol konkurensi, dan Anda mencapai hasil yang sama tanpa menentukan FOR UPDATE
secara eksplisit.
Untuk mengatasi masalah ini, Thread 1 harus
SELECT id FROM rooms FOR UPDATE
, sehingga mencegah Thread 2 menghapus darirooms
sampai Thread 1 selesai. Apakah itu benar?
Ini tergantung pada kontrol konkurensi yang digunakan sistem database Anda.
-
MyISAM
diMySQL
(dan beberapa sistem lama lainnya) mengunci seluruh tabel selama kueri. -
Di
SQL Server
,SELECT
kueri menempatkan kunci bersama pada catatan / halaman / tabel yang telah mereka periksa, sementaraDML
kueri menempatkan kunci pembaruan (yang kemudian dipromosikan menjadi eksklusif atau diturunkan ke kunci bersama). Kunci eksklusif tidak kompatibel dengan kunci bersama, jadiSELECT
atauDELETE
kueri akan terkunci hingga sesi lain dilakukan. -
Dalam database yang menggunakan
MVCC
(sepertiOracle
,PostgreSQL
,MySQL
denganInnoDB
), sebuahDML
query membuat salinan catatan (dalam satu atau lain cara) dan umumnya pembaca tidak memblokir penulis dan sebaliknya. Untuk database ini,SELECT FOR UPDATE
akan berguna:itu akan mengunciSELECT
atauDELETE
kueri hingga sesi lain dilakukan, sepertiSQL Server
tidak.
Kapan seseorang harus menggunakan
REPEATABLE_READ
isolasi transaksi versusREAD_COMMITTED
denganSELECT ... FOR UPDATE
?
Secara umum, REPEATABLE READ
tidak melarang baris phantom (baris yang muncul atau hilang dalam transaksi lain, bukan diubah)
-
Di
Oracle
danPostgreSQL
sebelumnya versi,REPEATABLE READ
sebenarnya adalah sinonim untukSERIALIZABLE
. Pada dasarnya, ini berarti bahwa transaksi tidak melihat perubahan yang dilakukan setelah dimulai. Jadi dalam pengaturan ini,Thread 1
terakhir kueri akan mengembalikan ruangan seolah-olah tidak pernah dihapus (yang mungkin atau mungkin bukan yang Anda inginkan). Jika Anda tidak ingin menampilkan ruangan setelah dihapus, Anda harus mengunci baris denganSELECT FOR UPDATE
-
Di
InnoDB
,REPEATABLE READ
danSERIALIZABLE
adalah hal yang berbeda:pembaca diSERIALIZABLE
mode mengatur kunci tombol berikutnya pada catatan yang mereka evaluasi, secara efektif mencegahDML
. bersamaan pada mereka. Jadi, Anda tidak memerlukanSELECT FOR UPDATE
dalam mode serial, tetapi membutuhkannya dalamREPEATABLE READ
atauREAD COMMITED
.
Perhatikan bahwa standar pada mode isolasi memang menetapkan bahwa Anda tidak melihat keanehan tertentu dalam kueri Anda tetapi tidak menentukan caranya (dengan penguncian atau dengan MVCC
atau sebaliknya).
Ketika saya mengatakan "Anda tidak perlu SELECT FOR UPDATE
" Saya benar-benar harus menambahkan "karena efek samping dari implementasi mesin basis data tertentu".