Rumah > Artikel > pangkalan data > Artikel yang menganalisis secara ringkas bagaimana MySQL menyelesaikan masalah membaca hantu
Bagaimana MySQL menyelesaikan masalah bacaan hantu? Artikel berikut akan membolehkan anda bercakap tentang isu ini. Mari baca artikel dengan soalan!
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 UNCOMMITTED
Di 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 SERIALIZABLE
Di 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?
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
: 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 InnoDB
Enjin storan akan menjananya untuk kami dengan lebih terperinci compact
Format baris adalah seperti berikut:
然后将roll_pointer
undolog
yang dimasukkan ke dalam rekod ini ialah , 事务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) 80
roll_pointer
Andaikan bahawa dua seterusnya <.> urus niaga adalah
dan melaksanakan operasi 事务id
pada rekod ini: 100
200
UPDATE
Setiap kali rekod diubah suai,
-- 事务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: INSERT
undo日志
undo日志
Selepas setiap kemas kini rekod ini, nilai lama akan dimasukkan ke dalam
Kami memanggil senarai terpaut ini , rantai versi Nod kepala ialah nilai terkini rekod semasa. Selain itu, setiap versi juga mengandungi undo日志
roll_pointer
版本链
事务id
2.2 ReadView
; 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 READ
SERIALIZABLE
READ UNCOMMITTED
: Apabila menjana SERIALIZABLE
, id benda aktif ditetapkan read committed
REPEATABLE READ
m_ids
read view
: menunjukkan bahawa apabila menjana min_trx_id
m_ids的最小值
: apabila mencipta max_trx_id
read view
Dengan ini creator_trx_id
read view
ReadView
Jika ID transaksi versi yang diakses kurang daripada , ini bermakna, Apabila
creator_trx_id
, ia bermakna apabila min_trx_id
read view
Jika versi yang diakses perkara 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
transaction_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:
Pada masa ⑥, kerana transaksi trx 200
melaksanakan penyerahan transaksi, rantai versi rekod baris id=1 adalah seperti berikut:
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 可重复读
.
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:
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!