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 dariroomssampai Thread 1 selesai. Apakah itu benar?
Ini tergantung pada kontrol konkurensi yang digunakan sistem database Anda.
-
MyISAMdiMySQL(dan beberapa sistem lama lainnya) mengunci seluruh tabel selama kueri. -
Di
SQL Server,SELECTkueri menempatkan kunci bersama pada catatan / halaman / tabel yang telah mereka periksa, sementaraDMLkueri menempatkan kunci pembaruan (yang kemudian dipromosikan menjadi eksklusif atau diturunkan ke kunci bersama). Kunci eksklusif tidak kompatibel dengan kunci bersama, jadiSELECTatauDELETEkueri akan terkunci hingga sesi lain dilakukan. -
Dalam database yang menggunakan
MVCC(sepertiOracle,PostgreSQL,MySQLdenganInnoDB), sebuahDMLquery membuat salinan catatan (dalam satu atau lain cara) dan umumnya pembaca tidak memblokir penulis dan sebaliknya. Untuk database ini,SELECT FOR UPDATEakan berguna:itu akan mengunciSELECTatauDELETEkueri hingga sesi lain dilakukan, sepertiSQL Servertidak.
Kapan seseorang harus menggunakan
REPEATABLE_READisolasi transaksi versusREAD_COMMITTEDdenganSELECT ... FOR UPDATE?
Secara umum, REPEATABLE READ tidak melarang baris phantom (baris yang muncul atau hilang dalam transaksi lain, bukan diubah)
-
Di
OracledanPostgreSQLsebelumnya versi,REPEATABLE READsebenarnya adalah sinonim untukSERIALIZABLE. Pada dasarnya, ini berarti bahwa transaksi tidak melihat perubahan yang dilakukan setelah dimulai. Jadi dalam pengaturan ini,Thread 1terakhir 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 READdanSERIALIZABLEadalah hal yang berbeda:pembaca diSERIALIZABLEmode mengatur kunci tombol berikutnya pada catatan yang mereka evaluasi, secara efektif mencegahDML. bersamaan pada mereka. Jadi, Anda tidak memerlukanSELECT FOR UPDATEdalam mode serial, tetapi membutuhkannya dalamREPEATABLE READatauREAD 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".