MySQL 事務(wù)篇

并行事務(wù)會(huì)引發(fā)什么問題?

? ? ? 同時(shí)處理多個(gè)事務(wù)的時(shí)候,就可能出現(xiàn)臟讀(dirty read)、不可重復(fù)讀(non-repeatable read)、幻讀(phantom read)的問題。

1、臟讀。如果一個(gè)事務(wù)「讀到」了另一個(gè)「未提交事務(wù)修改過的數(shù)據(jù)」,就意味著發(fā)生了「臟讀」現(xiàn)象.

2、不可重復(fù)讀。在一個(gè)事務(wù)內(nèi)多次讀取同一個(gè)數(shù)據(jù),如果出現(xiàn)前后兩次讀到的數(shù)據(jù)不一樣的情況,就意味著發(fā)生了「不可重復(fù)讀」現(xiàn)象。

3、幻讀。在一個(gè)事務(wù)內(nèi)多次查詢某個(gè)符合查詢條件的「記錄數(shù)量」,如果出現(xiàn)前后兩次查詢到的記錄數(shù)量不一樣的情況,就意味著發(fā)生了「幻讀」現(xiàn)象

事務(wù)有哪些特性?

? ? ? 事務(wù)的四大特性 : ACID

1、原子性(Atomicity): 一個(gè)事務(wù)中的所有操作,要么全部完成,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié), 不會(huì)出現(xiàn) a 扣錢了, b 沒加錢。

2、一致性(Consistency):是指事務(wù)操作前和操作后,數(shù)據(jù)滿足完整性約束,數(shù)據(jù)庫保持一致性狀態(tài), 總錢數(shù)不會(huì)少

3、隔離性(Isolation): 數(shù)據(jù)庫允許多個(gè)并發(fā)事務(wù)同時(shí)對(duì)其數(shù)據(jù)進(jìn)行讀寫和修改的能力, 每個(gè)事務(wù)都有一個(gè)完整的數(shù)據(jù)空間,對(duì)其他并發(fā)事務(wù)是隔離的, 也就是 a 購買不會(huì)導(dǎo)致 b 購買

4、持久性(Durability):事務(wù)處理結(jié)束后,對(duì)數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會(huì)丟失

InnoDB 引擎通過什么技術(shù)來保證事務(wù)的這四個(gè)特性的呢?

1、原子性 : 通過undo log (回滾日志) 實(shí)現(xiàn)

2、隔離性 : 通過 MVCC (多并發(fā)版本控制) 或鎖機(jī)制保證

3、持久性 : 通過 redo log (重做日志) 實(shí)現(xiàn)

4、一致性 : 通過原子性 + 隔離性 + 持久性實(shí)現(xiàn)

事務(wù)的隔離級(jí)別有哪些?

1、讀未提交(read uncommitted),指一個(gè)事務(wù)還沒提交時(shí),它做的變更就能被其他事務(wù)看到, 可能發(fā)生臟讀、不可重復(fù)讀和幻讀現(xiàn)象。

2、讀提交(read committed),指一個(gè)事務(wù)提交之后,它做的變更才能被其他事務(wù)看到, 可能發(fā)生不可重復(fù)讀和幻讀現(xiàn)象

3、可重復(fù)讀(repeatable read),指一個(gè)事務(wù)執(zhí)行過程中看到的數(shù)據(jù),一直跟這個(gè)事務(wù)啟動(dòng)時(shí)看到的數(shù)據(jù)是一致的**,可能發(fā)生幻讀現(xiàn)象, 但是它很大程度上避免幻讀現(xiàn)象, MySQL InnoDB 引擎的默認(rèn)隔離級(jí)別。

4、串行化(serializable );會(huì)對(duì)記錄加上讀寫鎖,在多個(gè)事務(wù)對(duì)這條記錄進(jìn)行讀寫操作時(shí),如果發(fā)生了讀寫沖突的時(shí)候,后訪問的事務(wù)必須等前一個(gè)事務(wù)執(zhí)行完成,才能繼續(xù)執(zhí)行。

這四種隔離級(jí)別具體是如何實(shí)現(xiàn)的呢?

1、讀未提交 : 直接讀取最新的數(shù)據(jù)。

2、串行化 : 讀寫鎖。

3、讀提交和可重復(fù)讀 : 通過 Read View 來實(shí)現(xiàn) , 區(qū)別在于生成 Read View 的時(shí)機(jī)不同,。

3-1、讀提交是在「每個(gè)語句執(zhí)行前」都會(huì)重新生成一個(gè) Read View。

3-2、可重復(fù)讀是「啟動(dòng)事務(wù)時(shí)」生成一個(gè) Read View。

Read View 在 MVCC 里如何工作的?

m_ids(Read View中未提交事務(wù)ID列表) :指的是在創(chuàng)建 Read View 時(shí),當(dāng)前數(shù)據(jù)庫中啟動(dòng)但是未提交的事務(wù) id 列表,注意是一個(gè)列表。

min_trx_id(Read View中 未提交事務(wù)列表中事務(wù)id最小的一個(gè)) : 指的是在創(chuàng)建 Read View 時(shí), 啟動(dòng)但是未提交的事務(wù) id 列表中事務(wù) id 最小的值。

max_trx_id(Read View中? 未提交事務(wù)列表中預(yù)留下一個(gè)事務(wù)的ID值) :這個(gè)并不是 m_ids 的最大值,而是創(chuàng)建 Read View 時(shí)當(dāng)前數(shù)據(jù)庫中應(yīng)該給下一個(gè)事務(wù)的 id 值,也就是全局事務(wù)中最大的事務(wù) id 值 + 1。

creator_trx_id :指的是創(chuàng)建該 Read View 的事務(wù)的事務(wù) id

聚簇索引記錄中的兩個(gè)隱藏列。

trx_id : 該事務(wù)的事務(wù) id

roll_pointer : 這個(gè)隱藏列是個(gè)指針,指向每一個(gè)舊版本記錄,可以通過它找到修改前的記錄

MVCC 工作過程

一個(gè)事務(wù)去訪問記錄的時(shí)候,除了自己的更新記錄總是可見之外,還有這幾種情況:

1、如果該記錄的 trx_id 小于 Read View 的 min_trx_id, 說明該記錄是在創(chuàng)建 Read View 之前的事務(wù)生成的, 可見

2、如果該記錄的 trx_id 大于 Read View 的 max_trx_id, 說明該記錄是在創(chuàng)建 Read View 之后的事務(wù)生成的, 不可見。

3、如果記錄的 trx_id 值在 Read View 的 min_trx_id 和 max_trx_id 之間, 需要判斷 trx_id 是否在 m_ids 列表中

? ? 3-1、如果 trx_id 在 m_ids 列表中, 說明創(chuàng)建該記錄的事務(wù)還未提交, 不可見。

? ? 3-2、如果 trx_id 不在 m_ids 列表中, 說明創(chuàng)建該記錄的事務(wù)已經(jīng)提交, 可見。

當(dāng)前不可見的可以通過 roll_pointer 指針尋找 undo log 版本鏈找到事務(wù)開始時(shí)的數(shù)據(jù)。這種通過「版本鏈」來控制并發(fā)事務(wù)訪問同一個(gè)記錄時(shí)的行為就叫 MVCC(多版本并發(fā)控制)

MySQL 可重復(fù)讀隔離級(jí)別,完全解決幻讀了嗎?

? ? ? 并沒有,還是會(huì)發(fā)生幻讀現(xiàn)象。通過串行讀來避免。

當(dāng)前讀是如何避免幻讀的?

? ? ? MySQL 里除了普通查詢是快照讀其他都是當(dāng)前讀(讀提交),比如 update、insert、delete,這些語句執(zhí)行前都會(huì)查詢最新版本的數(shù)據(jù),然后再做進(jìn)一步的操作, 另外, select ... for update 這種查詢語句是當(dāng)前讀,每次執(zhí)行的時(shí)候都是讀取最新的數(shù)據(jù)。

? ? ? ? Innodb 引擎為了解決「可重復(fù)讀」隔離級(jí)別使用「當(dāng)前讀」而造成的幻讀問題,就引出了間隙鎖(next-key lock 是間隙鎖+記錄鎖的組合)。

幻讀被完全解決了嗎?

? ? ? 可重復(fù)讀隔離級(jí)別下雖然很大程度上避免了幻讀,但是還是沒有能完全解決幻讀。

總結(jié)

? ? ? 在多線程并發(fā)的場景下,會(huì)經(jīng)常產(chǎn)生事務(wù)并行,而并行事務(wù)會(huì)發(fā)生臟讀、不可重復(fù)讀、幻讀問題,這跟事務(wù)本身的特性相駁。事務(wù)的特性:ACID? 原子性 一致性 隔離性 持久性。而這些特性是通過一些邏輯進(jìn)行保證,但是如果每次操作都保證絕對(duì)的一致性,會(huì)非常影響性能。為了盡可能的保證性能,事務(wù)的隔離級(jí)別分為4種讀未提交、讀提交、可重復(fù)讀、串行讀。可以根據(jù)業(yè)務(wù)場景選擇不同的隔離級(jí)別進(jìn)行處理,而這些隔離級(jí)別通過MVCC/讀寫鎖來保證。另外mysql默認(rèn)可重復(fù)讀隔離級(jí)別。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 事務(wù)介紹 在MySQL中的事務(wù)是由存儲(chǔ)引擎實(shí)現(xiàn)的,而且支持事務(wù)的存儲(chǔ)引擎不多,我們主要講解InnoDB存儲(chǔ)引...
    MiniSoulBigBang閱讀 842評(píng)論 0 3
  • 什么是事務(wù) 在計(jì)算機(jī)術(shù)語[https://baike.baidu.com/item/%E6%9C%AF%E8%AF...
    胡GaQue閱讀 100評(píng)論 0 0
  • 讀的類型 在RR級(jí)別中,通過MVCC機(jī)制,雖然讓數(shù)據(jù)變得可重復(fù)讀,但我們讀到的數(shù)據(jù)可能是歷史數(shù)據(jù),是不及時(shí)的數(shù)據(jù),...
    一秒一心跳閱讀 875評(píng)論 0 3
  • 事務(wù)可以用來維護(hù)數(shù)據(jù)庫的完整性,保證成批的 SQL 語句要么全部執(zhí)行,要么全部不執(zhí)行。MySQL 中只有使用了 I...
    伊凡的一天閱讀 2,494評(píng)論 3 22
  • 事務(wù)的四大特性(簡稱ACID) 數(shù)據(jù)庫如果支持事務(wù)的操作,那么就具備以下四個(gè)特性: 1、原子性(Atomicity...
    gregoriusxu閱讀 368評(píng)論 0 0

友情鏈接更多精彩內(nèi)容