Rumah  >  Artikel  >  pangkalan data  >  Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu

Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu

青灯夜游
青灯夜游ke hadapan
2023-02-06 20:14:162042semak imbas

Bagaimana MySQL menyelesaikan masalah bacaan hantu? Artikel berikut akan membolehkan anda bercakap tentang isu ini. Mari baca artikel dengan soalan!

Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu

  Antara soalan temu bual frekuensi tinggi Jin Busan dan Yin Busi, ciri transaksi MySQL, tahap pengasingan dan isu lain juga merupakan salah satu esei lapan bahagian yang sangat klasik. Berhadapan dengan Soalan ini, dianggarkan kebanyakan rakan sudah biasa dengan mereka:

Ciri-ciri transaksi (ACID) : 原子性 (Atomicity), 隔离性 (Isolation ), 一致性 (Consistency) dan 持久性

Tahap pengasingan : 读取未提交 (READ UNCOMMITTED), 读取已提交 (READ COMMITTED), 可重复读 (REPEATABLE READ), 可串行化(SERIALIZABLE)

Masalah yang disebabkan oleh setiap tahap pengasingan ialah:

  • READ UNCOMMITTEDDi bawah tahap pengasingan, 脏读, Isu 不可重复读 dan 幻读
  • READ COMMITTED Di bawah tahap pengasingan, isu 不可重复读 dan 幻读 mungkin berlaku, tetapi isu 脏读 tidak boleh berlaku
  • REPEATABLE READ tahap pengasingan Di bawah tahap pengasingan, 幻读 masalah mungkin berlaku, tetapi masalah 脏读 dan 不可重复读 tidak boleh berlaku
  • SERIALIZABLEDi bawah tahap pengasingan, pelbagai masalah tidak boleh berlaku

Tahap pengasingan yang disokong lalai untuk enjin storan MySQL InnoDB ialah BACA-REPEATABLE (boleh dibaca semula) Daripada takrifan empat tahap pengasingan standard SQL di atas, kita tahu bahawa REPEATABLE-READ(可重复读) tidak boleh menghalang . Pembacaan hantu, tetapi kita semua tahu bahawa enjin storan MySQL InnoDB menyelesaikan masalah bacaan hantu, jadi bagaimanakah ia menyelesaikannya?

1. Format baris

  Sebelum memasuki topik, mari kita memahami secara umum apa itu format baris. Ini akan membantu kita memahami format baris berikut ialah Cara rekod baris dalam jadual disimpan pada cakera, enjin storan Innodb mempunyai sejumlah 4 jenis format baris yang berbeza: compact, redundant, dynamic, compress walaupun terdapat banyak format baris, pada dasarnya, mereka pada dasarnya adalah sama, seperti berikut, dalam format baris compact: Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu  Seperti yang dapat dilihat dari gambar, rekod lengkap sebenarnya boleh dibahagikan kepada dua bahagian: 记录的额外信息 dan 记录的真实数据, 记录的额外信息 masing-masing Ia adalah 变长字段长度列表, NULL值列表 dan 记录头信息, dan 记录的真实数据 sebagai tambahan kepada lajur yang ditentukan kami sendiri, MySQL akan menambah beberapa lajur lalai pada setiap rekod, lajur lalai ini juga dipanggil 隐藏列, lajur khusus adalah seperti berikut :

列名 长度 描述
row_id 6个字节 行ID,唯一标识一条记录
transaction_id 6个字节 事务ID
roll_pointer 7个字节 回滚指针

Kami tidak perlu risau tentang nilai lajur tersembunyi InnoDBEnjin storan akan menjananya untuk kami dengan lebih terperinci compactFormat baris adalah seperti berikut:

Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu

  • transaction_id: transaction id: Setiap kali transaksi diubah suai rekod baris diubah suai, ID transaksi akan diberikan kepada lajur ini Versi lama data ditulis pada log undolog dan
  • menunjuk ke
  • , jadi lajur ini bersamaan dengan penunjuk lajur, anda boleh mencari maklumat sebelum pengubahsuaian 然后将roll_pointerundolog
2 Penjelasan terperinci tentang MVCC

rantaian Versi 2.1

Katakan terdapat rekod seperti berikut:

yang dimasukkan ke dalam rekod ini ialah Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu, 事务id Penunjuk adalah NULL (untuk memudahkan pemahaman, pembaca boleh memahaminya sebagai menunjuk ke NULL. Malah, bit pertama roll_pointer menandakan jenis log batal yang ditunjuknya Jika nilai bit ini ialah 1, ia bermakna ia menunjuk kepada Jenis log batal adalah masukkan batal) 80roll_pointer Andaikan bahawa dua seterusnya <.> urus niaga adalah

dan

dan melaksanakan operasi 事务id pada rekod ini: 100200UPDATE Setiap kali rekod diubah suai,

akan direkodkan, dan setiap
 -- 事务id=100
 update person set grade =20 where id =1;
 update person set grade =40 where id =1;
 -- 事务id=200
 update person set grade =70 where id =1;
juga mempunyai atribut

(undo日志 yang sepadan dengan operasi undo日志 tidak mempunyai atribut ini, kerana rekod tidak mempunyai versi yang lebih awal), anda boleh menyambungkan roll_pointer ini dan mengikatnya ke dalam senarai terpaut, jadi keadaan semasa adalah seperti gambar di bawah: INSERTundo日志undo日志  Selepas setiap kemas kini rekod ini, nilai lama akan dimasukkan ke dalam

, walaupun ia adalah versi lama bagi rekod, apabila bilangan kemas kini bertambah, semua versi akan disambungkan ke dalam senarai terpaut oleh atribut

Kami memanggil senarai terpaut ini Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu, rantai versi Nod kepala ialah nilai terkini rekod semasa. Selain itu, setiap versi juga mengandungi undo日志roll_pointer版本链事务id2.2 ReadView

 Empat tahap pengasingan untuk pangkalan data: 1) ; ; 3)

; 4)

; Sebagai contoh, read uncommitted, hanya membaca data rantaian versi setiap kali, terutamanya melalui kawalan kunci; baca perkara yang diserahkan, jadi untuk kedua-dua tahap pengasingan ini, isu teras ialah perkara dalam rantaian versi kelihatan kepada perkara semasa untuk menyelesaikan masalah ini, MySQL mencadangkan Konsep paparan baca, yang mengandungi empat konsep teras: read committed REPEATABLE READSERIALIZABLEREAD UNCOMMITTED: Apabila menjana SERIALIZABLE, id benda aktif ditetapkan read committedREPEATABLE READ

:
    , yang menjana bacaan Apabila melihat, nilai minimum perkara aktif
  • m_idsread view: menunjukkan bahawa apabila menjana
  • , sistem harus menetapkan nilai id perkara seterusnya
  • min_trx_idm_ids的最小值: apabila mencipta
  • Thing id, iaitu id perkara semasa.
  • max_trx_idread viewDengan ini
  • , apabila mengakses rekod, anda hanya perlu mengikut langkah-langkah di bawah untuk menentukan sama ada versi rekod tertentu kelihatan:
  • creator_trx_idread view
  • Apabila ID transaksi yang direkodkan adalah sama dengan
, ini bermakna transaksi semasa mengakses rekod yang diubah suai, jadi versi ini kelihatan

ReadViewJika ID transaksi versi yang diakses kurang daripada Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu , ini bermakna, Apabila

dicipta, perkara itu telah diserahkan, dan versi ini boleh dibaca kepada perkara semasa
  • Jika id perkara versi yang diakses lebih besar daripada atau sama dengan creator_trx_id, ia bermakna apabila
  • dicipta , bermakna ID perkara yang menjana rekod versi ini tidak dibuka sehingga
  • dijana, jadi versi ini tidak boleh dibaca oleh perkara semasa min_trx_idread viewJika versi yang diakses perkara
  • ada dalam koleksi
  • , Ini bermakna apabila max_trx_id dijana, transaksi masih aktif dan belum diserahkan, jadi versi ini tidak boleh diakses jika tiada, bermakna bahawa transaksi yang menjana versi ini apabila read view dibuat telah diserahkan dan boleh diaksesRead view
  • Nota: Perkara id untuk membaca perkara ialah 0transaction_id

    Dalam MySQL, perbezaan yang sangat besar antara tahap pengasingan READ COMMITTED dan REPEATABLE READ ialah mereka menjana ReadView pada masa yang berbeza:

    • READ COMMITTED - setiap satu dibaca Sebelum mengambil data, ReadView
    • REPEATABLE READ dijana - apabila data dibaca buat kali pertama, ReadView

    dijana dengan contoh terperinci di bawah. Apakah perbezaan antara kedua-duanya:

    时间编号
    trx 100 trx 200
    BEGIN;


    BEGIN; BEGIN;

    update person set grade =20 where id =1;

    update person set grade =40 where id =1;
    SELECT * FROM person WHERE id = 1;


    COMMIT;


    update person set grade =70 where id =1;
    SELECT * FROM person WHERE id = 1;



    COMMIT;
    ? COMMIT;

    Dalam masa ④, disebabkan transaksi trx 100 melaksanakan penyerahan transaksi, rantaian versi yang direkodkan dalam baris id=1 adalah seperti berikut:

    Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu Pada masa ⑥, kerana transaksi trx 200 melaksanakan penyerahan transaksi, rantai versi rekod baris id=1 adalah seperti berikut:

    Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu

    Pada masa ⑤, urus niaga trx 100 telah dilaksanakan Apabila pernyataan select dibuat, ReadView akan dijana terlebih dahulu Kandungan ReadView senarai m_ids ialah [100, 200], min_trx_id ialah. 100, max_trx_id ialah 201 dan creator_trx_id ialah 0, pada masa ini, pilih rekod yang boleh dilihat daripada rantai versi dan rentas rantai versi dari atas ke bawah: kerana gred=40, nilai trx_id ialah 100, dalam m_ids, jadi rekod tidak kelihatan begitu juga, Gred=20 juga tiada. Teruskan merentasi ke bawah, gred=20, nilai trx_id ialah 80, iaitu kurang daripada nilai ReadView min_trx_id dalam 100, jadi versi ini memenuhi keperluan dan rekod dengan tahap 10 dikembalikan kepada pengguna.

    Pada masa ⑧, jika tahap pengasingan urus niaga ialah READ COMMITTED, ReadView yang berasingan akan dijanakan kandungan senarai ReadView ini m_ids ialah [200], dan min_trx_id ialah 200, max_trx_id ialah 201 dan creator_trx_id ialah 0 Pada masa ini, pilih rekod yang boleh dilihat daripada rantaian versi dan rantaian versi dilalui dari atas ke bawah: kerana gred. =70, nilai trx_id ialah 200, dalam m_ids, jadi rekod tidak dapat dilihat terus ke bawah, nilai gred=40, trx_id ialah 100, yang lebih kecil daripada ReadView. nilai min_trx_id dalam 200, jadi versi ini Ia memenuhi keperluan, dan apa yang dikembalikan kepada pengguna ialah rekod dengan tahap 40.

    Pada masa ⑧, jika tahap pengasingan urus niaga ialah REPEATABLE READ, pada masa ⑧, ReadView berasingan tidak akan dijana, tetapi ReadView dari masa 5 akan digunakan, jadi satu dikembalikan kepada Tahap pengguna ialah 10. Hasil daripada dua pilihan adalah sama. Ini adalah maksud 可重复读.

    3. Ringkasan

    Dengan menganalisis penjelasan terperinci MVCC, dapat disimpulkan bahawa berdasarkan MVCC, di bawah tahap pengasingan RR, masalah 幻读 ialah diselesaikan dengan baik, tetapi Kami tahu bahawa select for update menjana bacaan semasa dan bukan lagi bacaan syot kilat Jadi dalam kes ini, bagaimanakah MySQL menyelesaikan masalah 幻读? Berdasarkan isu masa (memang mengambil banyak masa untuk menyusun dan melukis gambar), saya akan memberikan kesimpulan dahulu, dan kemudian menganalisis bagaimana MySQL menyelesaikan masalah 幻读 di bawah situasi bacaan semasa:

    • Bacaan Semasa: Gunakan Next-Key Lock (gap lock) untuk mengunci bagi memastikan bacaan hantu tidak berlaku

    Bagaimana gap lock menyelesaikan masalah bacaan hantu dalam situasi bacaan semasa Ya, rakan yang berminat boleh menambah follow dan like

    [Cadangan berkaitan: tutorial video mysql]

Atas ialah kandungan terperinci Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam