Apa perbedaan antara Non-Repeatable Read dan Phantom Read?

155

Apa perbedaan antara pembacaan yang tidak dapat diulang dan pembacaan hantu?

Saya telah membaca artikel Isolasi (sistem basis data) dari Wikipedia , tetapi saya punya beberapa keraguan. Dalam contoh di bawah ini, apa yang akan terjadi: baca yang tidak dapat diulang dan baca hantu ?

Transaksi A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
KELUARAN:
1----MIKE------29019892---------5000
Transaksi B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Transaksi A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Keraguan lain adalah, pada contoh di atas, level isolasi mana yang harus digunakan? Dan mengapa?

pengguna1357722
sumber

Jawaban:

166

Dari Wikipedia (yang memiliki contoh bagus dan terperinci untuk ini):

Pembacaan non-berulang terjadi, ketika selama transaksi, satu baris diambil dua kali dan nilai-nilai dalam baris berbeda antara pembacaan.

dan

Pembacaan hantu terjadi ketika, dalam suatu transaksi, dua query identik dieksekusi, dan kumpulan baris yang dikembalikan oleh query kedua berbeda dari yang pertama.

Contoh sederhana:

  • Pengguna A menjalankan kueri yang sama dua kali.
  • Di antaranya, Pengguna B menjalankan transaksi dan melakukan.
  • Bacaan yang tidak dapat diulang: Baris A yang ditanyakan pengguna A memiliki nilai yang berbeda untuk kedua kalinya.
  • Phantom baca: Semua baris dalam kueri memiliki nilai yang sama sebelum dan sesudah, tetapi baris yang berbeda sedang dipilih (karena B telah menghapus atau memasukkan beberapa). Contoh: select sum(x) from table;akan mengembalikan hasil yang berbeda walaupun tidak ada baris yang terpengaruh sendiri yang diperbarui, jika baris telah ditambahkan atau dihapus.

Dalam contoh di atas, level isolasi mana yang akan digunakan?

Level isolasi apa yang Anda butuhkan tergantung pada aplikasi Anda. Ada biaya tinggi ke tingkat isolasi "lebih baik" (seperti pengurangan konkurensi).

Dalam contoh Anda, Anda tidak akan membaca hantu, karena Anda hanya memilih dari satu baris (diidentifikasi dengan kunci utama). Anda dapat memiliki bacaan yang tidak dapat diulang, jadi jika itu merupakan masalah, Anda mungkin ingin memiliki tingkat isolasi yang mencegahnya. Di Oracle, transaksi A juga bisa mengeluarkan SELECT FOR UPDATE, maka transaksi B tidak dapat mengubah baris sampai A selesai.

Thilo
sumber
6
Saya tidak benar-benar memahami logika sintaksis seperti itu ...
Pembacaan
14
@serhio "non-repeatable" mengacu pada fakta bahwa Anda dapat membaca nilai satu kali dan mendapatkan x sebagai hasilnya, dan kemudian membaca lagi dan mendapatkan y sebagai hasilnya, jadi Anda tidak dapat mengulangi (non-repeatable) hasil yang sama dari dua pisahkan kueri dari baris yang sama, karena nilai baris itu diperbarui di antara bacaan.
BateTech
@Thilo Apa pun contoh kasus penggunaan nyata yang dapat dibaca berulang dapat menimbulkan masalah dan jika perlu?
user104309
Bagaimana jika PK dimodifikasi dalam transaksi lain? Bisakah itu menghasilkan bayangan yang dibaca? (Suatu hal yang aneh untuk dilakukan dalam banyak kasus, tetapi bukan tidak mungkin.)
jpmc26
1
Keduanya terdengar sama bagi saya
sn.anurag
127

Cara sederhana yang saya suka pikirkan adalah:

Pembacaan non-berulang dan phantom berkaitan dengan operasi modifikasi data dari transaksi yang berbeda, yang dilakukan setelah transaksi Anda dimulai, dan kemudian dibaca oleh transaksi Anda.

Pembacaan yang tidak dapat diulang adalah ketika transaksi Anda membaca UPDATES yang dilakukan dari transaksi lain. Baris yang sama sekarang memiliki nilai yang berbeda dengan ketika transaksi Anda dimulai.

Pembacaan hantu serupa tetapi ketika membaca dari SERI dan / atau HAPUS dari transaksi lain yang dilakukan. Ada baris atau baris baru yang telah menghilang sejak Anda memulai transaksi.

Pembacaan yang kotor mirip dengan pembacaan yang tidak dapat diulang dan phantom, tetapi berhubungan dengan membaca data yang TIDAK DIKOMPITASI, dan terjadi ketika PEMBARUAN, INSERT, atau HAPUS dari transaksi lain dibaca, dan transaksi lainnya belum melakukan data. Itu sedang membaca data "sedang berlangsung", yang mungkin tidak lengkap, dan mungkin tidak pernah benar-benar dilakukan.

BateTech
sumber
4
Ini ada hubungannya dengan tingkat isolasi transaksi dan konkurensi. Menggunakan tingkat isolasi default, Anda tidak akan mendapatkan pembacaan kotor, dan dalam kebanyakan kasus, Anda ingin menghindari pembacaan kotor. Ada tingkat isolasi atau petunjuk kueri yang akan memungkinkan pembacaan kotor, yang dalam beberapa kasus merupakan trade off yang dapat diterima untuk mencapai konkurensi yang lebih tinggi atau diperlukan karena kasus tepi, seperti pemecahan masalah dan transaksi yang sedang berlangsung dari koneksi lain. Adalah baik bahwa gagasan membaca kotor tidak lulus "tes bau" untuk Anda, bc sebagai aturan umum, mereka harus dihindari, tetapi memiliki tujuan
BateTech
1
@PHPAvenger di sini adalah kasus penggunaan untuk tingkat isolasi BACA YANG TIDAK DICATAT: selalu ada kemungkinan untuk menemui jalan buntu antara kueri pemilihan dan pembaruan (dijelaskan di sini ). Jika kueri pemilihan terlalu rumit untuk membuat indeks penutup, untuk menghindari kebuntuan Anda akan ingin menggunakan tingkat isolasi BACA yang TIDAK DIKOMPONI dengan risiko menemukan pembacaan kotor, tetapi seberapa sering Anda mengembalikan transaksi untuk khawatir tentang pembacaan yang kotor itu tidak menjadi permanen ?!
petrica.martinescu
1
@ petrica.martinescu masalah yang disebabkan oleh pembacaan yang kotor BUKAN hanya tentang apakah suatu transaksi dibatalkan atau tidak. Bacaan kotor dapat mengembalikan hasil yang sangat tidak akurat tergantung pada bagaimana data dalam transaksi yang tertunda telah dimodifikasi. Bayangkan sebuah transaksi yang melakukan serangkaian beberapa penghapusan, pembaruan, dan / atau sisipan. Jika Anda membaca data di tengah transaksi itu menggunakan "baca tidak berkomitmen", itu tidak lengkap. Level isolasi snapshot (dalam SQL Server) adalah alternatif yang jauh lebih baik untuk membaca tanpa komitmen. Kasing penggunaan yang valid untuk tingkat isolasi tanpa komitmen yang sudah dibaca dalam sistem produksi jarang ditemukan.
BateTech
2
@DiponRoy pertanyaan bagus. Penguncian yang diimplementasikan jika menggunakan isolasi readable read (RR) harus mencegah penghapusan terjadi pada baris yang telah dipilih. Saya telah melihat berbagai definisi level 2 iso selama bertahun-tahun, terutama yang mengatakan hantu adalah perubahan dalam koleksi / # baris yang dikembalikan dan RR adalah baris yang sama sedang diubah. Saya baru saja memeriksa dokumentasi MS SQL yang diperbarui mengatakan bahwa penghapusan dapat menyebabkan non-RR ( docs.microsoft.com/en-us/sql/odbc/reference/develop-app/... ) jadi saya pikir akan lebih aman untuk mengelompokkan penghapusan dalam kategori RR juga
BateTech
2
@ anir ya, sisipan dan penghapusan termasuk dalam bacaan kotor. Contoh: memulai transaksi, masukkan 2 dari 100 baris faktur pada koneksi a, sekarang koneksi b membaca 2 baris tersebut sebelum trx dilakukan dan sebelum 98 baris lainnya ditambahkan, sehingga tidak termasuk semua info untuk faktur. Ini akan menjadi bacaan kotor yang melibatkan sisipan.
BateTech
28

Seperti yang dijelaskan dalam artikel ini , anomali Baca Tidak Berulang terlihat sebagai berikut:

masukkan deskripsi gambar di sini

  1. Alice dan Bob memulai dua transaksi basis data.
  2. Bob membaca catatan posting dan nilai kolom judul adalah Transaksi.
  3. Alice memodifikasi judul catatan posting yang diberikan dengan nilai ACID.
  4. Alice melakukan transaksi basis datanya.
  5. Jika Bob membaca ulang catatan pos, ia akan mengamati versi yang berbeda dari baris tabel ini.

Dalam artikel ini tentang Phantom Read , Anda dapat melihat bahwa anomali ini dapat terjadi sebagai berikut:

masukkan deskripsi gambar di sini

  1. Alice dan Bob memulai dua transaksi basis data.
  2. Bob membaca semua catatan post_comment yang terkait dengan baris posting dengan nilai pengenal 1.
  3. Alice menambahkan catatan post_comment baru yang dikaitkan dengan baris posting yang memiliki nilai pengidentifikasi 1.
  4. Alice melakukan transaksi basis datanya.
  5. Jika Bob membaca kembali catatan post_comment yang memiliki nilai kolom post_id sama dengan 1, ia akan mengamati versi yang berbeda dari kumpulan hasil ini.

Jadi, sementara Non-Repeatable Read berlaku untuk satu baris, Phantom Read adalah tentang serangkaian catatan yang memenuhi kriteria pemfilteran kueri yang diberikan.

Vlad Mihalcea
sumber
3
visualisasi luar biasa @Vlad
dextermini
23

Baca fenomena

  • Bacaan kotor : baca data UNCOMMITED dari transaksi lain
  • Bacaan yang tidak dapat diulang : baca data COMMITTED dariUPDATEkueri dari transaksi lain
  • Phantom bertuliskan : baca data COMMITTED dariINSERTatauDELETEpermintaan dari transaksi lain

Catatan : HAPUS pernyataan dari transaksi lain, juga memiliki probabilitas yang sangat rendah untuk menyebabkan pembacaan yang tidak dapat diulang dalam kasus tertentu. Sayangnya, hal ini terjadi ketika pernyataan DELETE menghapus baris yang sama dengan yang ditanyakan oleh transaksi Anda saat ini. Tetapi ini adalah kasus yang jarang, dan jauh lebih tidak mungkin terjadi dalam database yang memiliki jutaan baris di setiap tabel. Tabel yang berisi data transaksi biasanya memiliki volume data tinggi di lingkungan produksi apa pun.

Kami juga dapat mengamati bahwa UPDATES mungkin merupakan pekerjaan yang lebih sering dalam kebanyakan kasus penggunaan daripada INSERT atau DELETES yang sebenarnya (dalam kasus seperti itu, bahaya pembacaan yang tidak dapat diulang hanya tinggal - pembacaan hantu tidak mungkin dalam kasus tersebut). Inilah sebabnya mengapa UPDAT diperlakukan berbeda dari INSERT-DELETE dan anomali yang dihasilkan juga dinamai berbeda.

Ada juga biaya pemrosesan tambahan yang terkait dengan penanganan untuk INSERT-DELETEs, daripada hanya menangani UPDATES.


Manfaat tingkat isolasi yang berbeda

  • READ_UNCOMMITTED mencegah apa pun. Ini adalah tingkat isolasi nol
  • READ_COMMITTED mencegah hanya satu, yaitu Kotor dibaca
  • REPEATABLE_READ mencegah dua anomali: Pembacaan kotor dan pembacaan tidak dapat diulang
  • SERIALIZABLE mencegah ketiga anomali: Pembacaan kotor, Pembacaan tidak dapat diulang dan pembacaan Phantom

Lalu mengapa tidak mengatur transaksi SERIALIZABLE setiap saat? Nah, jawaban untuk pertanyaan di atas adalah: Pengaturan SERIALIZABLE membuat transaksi sangat lambat , yang lagi-lagi tidak kita inginkan.

Bahkan konsumsi waktu transaksi dalam tingkat berikut:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED

Jadi pengaturan READ_UNCOMMITTED adalah yang tercepat .


Ringkasan

Sebenarnya kita perlu menganalisis use case dan memutuskan tingkat isolasi sehingga kita mengoptimalkan waktu transaksi dan juga mencegah sebagian besar anomali.

Perhatikan bahwa database secara default memiliki pengaturan REPEATABLE_READ.

Subhadeep Ray
sumber
1
UPDATE atau DELETE keduanya dapat terjadi untuk bacaan yang tidak dapat diulang atau hanya UPDATE?
Dipon Roy
1
UPDATE atau DELETE keduanya dapat dilakukan untuk bacaan yang tidak dapat diulang
niket patel
Sebenarnya kita dapat meringkas bahwa rata-rata pernyataan DELETE acak yang dieksekusi oleh transaksi lain pada database yang sama memiliki kemungkinan sangat rendah untuk menyebabkan pembacaan yang tidak dapat diulang untuk transaksi saat ini. Tetapi pernyataan penghapusan yang sama memiliki kemungkinan 100% menyebabkan Phantom membaca untuk transaksi saat ini. Terlihat seperti itu, tulisan saya agak salah jika Anda menganggapnya kata per kata. Tapi hei, saya sengaja menulis dengan cara ini untuk membuat semuanya lebih jelas bagi pembaca.
Subhadeep Ray
+1 untuk penjelasan yang sederhana dan mudah dimengerti. Namun saya pikir sebagian besar database (oracle, mysql) memiliki tingkat isolasi standar Baca
Komit
7

Ada perbedaan dalam implementasi antara kedua jenis tingkat isolasi ini.
Untuk "non-repeatable read", penguncian baris diperlukan.
Untuk "phantom read", penguncian ruang lingkup diperlukan, bahkan penguncian meja.
Kita dapat mengimplementasikan dua level ini dengan menggunakan protokol penguncian dua fase .

egraldlo
sumber
Untuk menerapkan pembacaan berulang atau serializable, tidak perlu menggunakan penguncian baris.
a_horse_with_no_name
5

Dalam sistem dengan bacaan yang tidak dapat diulang, hasil dari permintaan kedua Transaksi A akan mencerminkan pembaruan dalam Transaksi B - ia akan melihat jumlah yang baru.

Dalam sistem yang memungkinkan phantom membaca, jika Transaksi B menyisipkan baris baru dengan ID = 1, Transaksi A akan melihat baris baru ketika kueri kedua dijalankan; yaitu pembacaan hantu adalah kasus khusus pembacaan yang tidak dapat diulang.

Jeffrey Kemp
sumber
Saya kira penjelasan tentang phantom read tidak benar. Anda bisa mendapatkan phantom dibaca bahkan jika data non-komit tidak pernah terlihat. Lihat contoh di Wikipedia (ditautkan di komentar di atas).
Thilo
1

Jawaban yang diterima menunjukkan sebagian besar dari semua yang disebut perbedaan antara keduanya sebenarnya tidak signifikan sama sekali.

Jika "satu baris diambil dua kali dan nilai-nilai di dalam baris berbeda antara pembacaan", maka itu bukan baris yang sama (bukan tuple yang sama dalam pembicaraan RDB yang benar) dan itu memang berdasarkan definisi juga halnya bahwa "koleksi baris yang dikembalikan oleh kueri kedua berbeda dari yang pertama ".

Mengenai pertanyaan "tingkat isolasi mana yang harus digunakan", semakin banyak data Anda yang sangat penting bagi seseorang, di suatu tempat, semakin besar kemungkinan Serializable adalah satu-satunya pilihan yang masuk akal.

Erwin Smout
sumber
0

Saya pikir ada beberapa perbedaan antara Non-repeateable-read & phantom-read.

Non-berulang berarti ada transaksi derek A & B. jika B dapat melihat modifikasi A, jadi mungkin terjadi membaca kotor, jadi kami membiarkan B memperhatikan modifikasi A setelah A melakukan.

Ada masalah baru: kita membiarkan B memperhatikan modifikasi A setelah A melakukan, itu berarti A memodifikasi nilai baris yang dipegang B, kadang-kadang B akan membaca baris lagi, sehingga B akan mendapatkan nilai baru yang berbeda dengan pertama kali kita dapatkan, kami menyebutnya Non-berulang, untuk menangani masalah ini, kami membiarkan B mengingat sesuatu (karena saya belum tahu apa yang akan diingat) ketika B mulai.

Mari kita pikirkan solusi baru, kita dapat melihat ada masalah baru juga, karena kita membiarkan B mengingat sesuatu, jadi apa pun yang terjadi dalam A, B tidak dapat terpengaruh, tetapi jika B ingin memasukkan beberapa data ke dalam tabel dan B periksa tabel untuk memastikan tidak ada catatan, tetapi data ini telah dimasukkan oleh A, jadi mungkin terjadi beberapa kesalahan. Kami menyebutnya Phantom-read.

Han R
sumber
0

non-repeatable read adalah level isolasi dan phantom read (membaca nilai yang dikomit oleh transaksi lain) adalah sebuah konsep (tipe pembacaan misalnya pembacaan kotor atau pembacaan snapshot). Tingkat isolasi baca yang tidak dapat diulang memungkinkan membaca hantu tetapi tidak membaca kotor atau membaca snapshot.

sn.anurag
sumber