自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解鎖MySQL的黑科技:事務(wù)與隔離

數(shù)據(jù)庫 MySQL
MySQL 中,問得最多的就是事務(wù)、隔離級別以及 MVCC 這幾個,無論是互聯(lián)網(wǎng)大廠、小廠,甚至是國企,它們的覆蓋率竟高達(dá) 80%。其實(shí)面試官也知道,八股文誰都會背,但是可以說明白,甚至說透徹的候選人卻是鳳毛麟角。

1. 引言

大家好,我是小?,一個漂泊江湖多年的 985 非科班程序員,曾混跡于國企、互聯(lián)網(wǎng)大廠和創(chuàng)業(yè)公司的后臺開發(fā)攻城獅。

最近小?在梳理我之前的面試資料時發(fā)現(xiàn),面試過程中,基本上都會問到 MySQL 數(shù)據(jù)庫相關(guān)的知識點(diǎn)。

而 MySQL 中,問得最多的就是事務(wù)、隔離級別以及 MVCC 這幾個,無論是互聯(lián)網(wǎng)大廠、小廠,甚至是國企,它們的覆蓋率竟高達(dá) 80%。

其實(shí)面試官也知道,八股文誰都會背,但是可以說明白,甚至說透徹的候選人卻是鳳毛麟角。

所以今天小?就帶大家來解鎖那些藏在 MySQL 底層的黑科技:事務(wù)與隔離。

2、事務(wù)

2.1 直播打賞

首先,讓我們來談?wù)勈聞?wù)。

事務(wù)就像一場魔法表演,它可以確保一系列數(shù)據(jù)庫操作要么全部執(zhí)行成功,要么一點(diǎn)都不執(zhí)行。

假設(shè)你在看直播時,想打賞 500 塊給美女主播,這時需要扣除你的賬戶余額,并同時增加美女主播的賬戶金額。

如果轉(zhuǎn)賬的兩個操作中的一個失敗,那你就可能損失金錢或者讓金錢消失不見,美女主播也就收不到錢了。

這時,事務(wù)就派上用場了。

它可以保證這兩個操作要么同時成功,要么同時失敗,絕不會出現(xiàn)一半成功一半失敗的尷尬局面。

所以,我們總結(jié)一下:

Q:數(shù)據(jù)庫為什么要有事務(wù)?

A:為了保證業(yè)務(wù)正常運(yùn)轉(zhuǎn),數(shù)據(jù)最終一致。

2.2 事務(wù)特性

明白了什么是事務(wù),以及為什么需要事務(wù)。

接下來我們聊一聊事務(wù)的 4 個特性:原子性、一致性、隔離性和持久性,簡稱 ACID。

原子性(Atomicity)

原子性是指事務(wù)包含的操作要么全部成功,要么全部不成功。

比如 A、B 賬戶的初始余額為 800 元,100元。此時,A 向 B 轉(zhuǎn)賬 500 元,那么分解開來就是 A 賬戶減 500 元,B 賬戶加 500 元。

最終結(jié)果是 A 賬戶余額為 300 元,B 賬戶余額為 600 元。這兩個賬戶余額更新的操作,要么全部執(zhí)行,要么都不執(zhí)行。

拿給美女主播打賞的例子,原子性可以保證:要么錢還在,要么錢轉(zhuǎn)到主播賬戶上并收獲主播的一聲謝謝哥哥!

一致性(Consistency)

事務(wù)執(zhí)行前,和執(zhí)行后都會保持一致性狀態(tài)。

A、B 賬戶在轉(zhuǎn)賬后,會發(fā)生兩種情況:

  1. 錢轉(zhuǎn)到 B 賬戶里了,這時 A、B 賬戶分別為 300、600 元;
  2. 錢轉(zhuǎn)出去的過程中數(shù)據(jù)庫網(wǎng)絡(luò)斷開,事務(wù)回滾了,A、B 賬戶還是 800、100 元。

無論怎樣,事務(wù)發(fā)生前后,A、B 銀行賬戶的總額都應(yīng)該為 900 元,這就是前后一致性。

隔離性(Isolation)

隔離性是當(dāng)多個用戶并發(fā)訪問數(shù)據(jù)庫時,不管是不是操作同一個庫、還是同一張表,數(shù)據(jù)庫為每一個用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個并發(fā)事務(wù)之間也要相互隔離。

比如,A 向 B 轉(zhuǎn)賬的時候,不管別人怎么轉(zhuǎn)賬,都不會影響他們的交易。

圖片圖片

拿給美女主播打賞的例子,隔離性就是:不管有多少人在給主播打賞,都不會影響你轉(zhuǎn)錢的事務(wù),也就不會影響主播叫你一聲好哥哥!

持久性(Durability)

一個事務(wù)一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是持久性的【即保存到磁盤里】,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務(wù)的操作。

拿給美女主播打賞的例子,持久性就是:你只要給主播轉(zhuǎn)了錢,錢就進(jìn)了她的賬戶,無論收獲主播的多少聲謝謝好哥哥,錢也回不來了。

接下來,我們總結(jié)一下:

  • Q:為什么事務(wù)有這幾大特性?
  • A:我們要保證事務(wù)的數(shù)據(jù)一致性,就需要一些手段來實(shí)現(xiàn),這幾種手段就是事務(wù)的幾個特性。

它們分別是原子性、一致性、隔離性和持久性,其中一致性是目的,而原子性、一致性和隔離性都是為了實(shí)現(xiàn)數(shù)據(jù)一致性的手段。

3. 事務(wù)并發(fā)和隔離

事務(wù)并發(fā)

并發(fā)是指計(jì)算機(jī)系統(tǒng)或程序在同一時間內(nèi)同時處理多個任務(wù)或操作的能力,也就是允許多個用戶進(jìn)程去處理同一塊臨界區(qū)。

想從進(jìn)程或處理器的角度來理解并發(fā)的,可以看我之前的這篇文章:GPM調(diào)度模型

拿打賞主播來舉例,并發(fā)就是多個觀眾都想打賞主播,如果你們一起轉(zhuǎn)錢,那主播的賬戶余額該怎么修改呢?

這里的任務(wù)就是轉(zhuǎn)賬,用戶進(jìn)程就是負(fù)責(zé)交易的服務(wù)器進(jìn)程,臨界區(qū)就是主播賬戶的存儲空間。

如果出現(xiàn)了事務(wù)并發(fā),就會帶來一些意想不到的問題,例如常見的臟寫、臟讀、重復(fù)讀和幻讀。

臟寫

臟寫是指:在事務(wù)并發(fā)的時候,一個事務(wù)可以修改另外一個正在進(jìn)行中的事務(wù)的數(shù)據(jù),這可能會導(dǎo)致一個寫的事務(wù)會覆蓋另外一個寫的事務(wù)數(shù)據(jù)。

當(dāng)你和小帥一起給美女主播打賞時,你打賞了 500 塊,小帥打賞了 1000 塊,在寫入數(shù)據(jù)庫的時候,你寫入的數(shù)據(jù)被小帥的數(shù)據(jù)給覆蓋了。

最后導(dǎo)致的結(jié)果就是,你錢沒了,而美女主播在直播間說的是謝謝小帥哥哥的打賞!

事務(wù)隔離

500 塊錢沒了,美女主播還不理你,你很傷心,但是不知道怎么辦?

別難過!事務(wù)隔離可以幫你。

MySQL 提供了事務(wù)隔離級別,包括:讀未提交、讀已提交、可重復(fù)讀以及串行化,來解決事務(wù)中各種并發(fā)問題,專治各種不開心。

RU - 讀未提交(Read uncommitted)

RU(讀未提交)是指,如果一個事務(wù)開始寫數(shù)據(jù),則另外一個事務(wù)不允許同時進(jìn)行寫操作,但允許其他事務(wù)讀取此行數(shù)據(jù)。

RU 可以排他寫,但是不排斥讀線程實(shí)現(xiàn)。

這種隔離級別解決了上面的臟寫問題,但可能會出現(xiàn)臟讀,即事務(wù) B 讀取到了事務(wù) A 未提交的數(shù)據(jù)。

你想給美女主播打賞 500 塊,發(fā)現(xiàn)銀行卡余額只有 300 塊,這時你想到了前幾天找你借了 500 塊錢的小帥,于是讓小帥還錢。

小帥非常清楚數(shù)據(jù)庫的事物隔離機(jī)制,知道你處于 RU 的事務(wù)隔離級別。于是說馬上還你錢,這時出現(xiàn)了以下情況:

圖片圖片

  • 小帥:開啟事務(wù) A,給你轉(zhuǎn)錢 500,事務(wù)未提交;
  • 你:開啟事務(wù) B,查詢余額,發(fā)現(xiàn)余額已經(jīng)加了 500,于是把小帥的借條撕掉,并準(zhǔn)備給主播打賞;
  • 小帥:看到借條已經(jīng)沒了,于是撤銷事務(wù) A。他的錢一分沒少,而你只讀到了他事務(wù) A 里的余額,但是真實(shí)的余額沒有增加,即發(fā)生了臟讀;
  • 你:打賞付款時余額不足,損失了價(jià)值 500 塊錢的借條。

你非常失望,打算和小帥絕交,然后繼續(xù)學(xué)習(xí)剩下的隔離機(jī)制,看看怎么避免臟讀發(fā)生。

RC - 讀已提交(Read committed)

該隔離級別在一個事務(wù)進(jìn)行數(shù)據(jù)寫入時,不允許別的事務(wù)對該行數(shù)據(jù)進(jìn)行訪問(包括讀寫)。這樣就可以保證事務(wù)讀到的數(shù)據(jù)一定是已經(jīng)提交了的,解決了臟讀的問題。

但是 RC 會出現(xiàn)不可重復(fù)讀的問題,比如:事務(wù) A 需要讀取兩次數(shù)據(jù),在讀取完第一次數(shù)據(jù)后,有另一個事務(wù) B 對該數(shù)據(jù)進(jìn)行的更新并提交事務(wù)。

此時事務(wù) A 再次讀取該數(shù)據(jù)時,數(shù)據(jù)已經(jīng)發(fā)生了改變,即事務(wù)中兩次讀取的數(shù)據(jù)不一致。

小帥為了挽回友情,給你轉(zhuǎn)了 520 塊錢,但是他覺得只還你 500 塊就可以,所以讓你還他 20 塊錢。

你這會忙著看美女主播,沒有時間轉(zhuǎn)錢,他建議你把銀行卡的賬號密碼告訴他,他只轉(zhuǎn) 20。

為了保險(xiǎn)起見,你打開了一個事務(wù)去查詢銀行卡余額,并告訴了小帥密碼,接下來發(fā)生了如下場景:

  • 你:開啟事務(wù) A,查詢銀行卡余額為 820;
  • 小帥:開啟事務(wù) B,提款 800,并提交了事務(wù) B;
  • 你:在事務(wù) A 中再次查詢余額時,發(fā)現(xiàn)銀行卡只有 20 塊錢了,發(fā)生了不可重復(fù)讀。

不僅被借的錢沒拿到,又損失了 280 塊錢,你越想越氣,罵了小帥一頓。然后繼續(xù)學(xué)習(xí)隔離機(jī)制,看看怎么防止不可重復(fù)讀的問題。

RR - 可重復(fù)讀( Repeatable read)

在同一個事務(wù)內(nèi),多次讀取同一個數(shù)據(jù),在這個事務(wù)還未結(jié)束時,其他事務(wù)不能訪問該數(shù)據(jù)(包括讀寫)。

這種隔離級別下解決了臟讀和不可重復(fù)讀的問題,但是可能會出現(xiàn)幻讀。

如事務(wù) A 在多次讀取數(shù)據(jù)時,有另一個事務(wù) B 在數(shù)據(jù)行中間插入或刪除了數(shù)據(jù),此時事務(wù) A 再次讀取時,可能會發(fā)現(xiàn)數(shù)據(jù)的行數(shù)變了。

簡單來說,RR - 可重復(fù)讀可以保證當(dāng)前事務(wù)不會讀取到其他事務(wù)已提交的 update 操作,但無法感知其他事務(wù)的 insert 和 delete 操作。

小帥知道你不會再借錢了,還被你罵了一頓,心中不忿。就想著用你的銀行賬號搞事情,于是發(fā)生了接下來的場景:

  • 你:開啟事務(wù) A,想查詢一下剛才交易了幾次,事務(wù)里看到結(jié)果是 2 次;
  • 小帥:開啟事務(wù) B,發(fā)現(xiàn)已經(jīng)不能修改你的余額數(shù)據(jù),就索性往你的銀行卡里面寫入了 100 次交易記錄,交易金額高達(dá)數(shù)千萬,提交事務(wù) B;
  • 你:在事務(wù) A 里面繼續(xù)查詢交易次數(shù),發(fā)現(xiàn)變成了 102 次;

這時,警察叔叔找上門了,說有人舉報(bào)你惡意洗黑錢,需要協(xié)助調(diào)查一下。

還好,經(jīng)過一番解釋和通過銀行數(shù)據(jù)庫的日志調(diào)查,發(fā)現(xiàn)是有人惡意篡改交易記錄,你平安無事回到了家。

這時,你痛定思痛,驚覺交友不慎!于是沉下心來繼續(xù)學(xué)習(xí)隔離機(jī)制。

可串行化(Serializable)

該隔離級別下,事務(wù)只能依次執(zhí)行,解決了臟讀、不可重復(fù)讀和幻讀的問題。但是代價(jià)較高,性能很低,一般很少使用。

在這種情況下,每次有觀眾和你一樣想給主播打賞,都需要排隊(duì)等候,直到前面的交易事務(wù)完全結(jié)束。

這時,你了解到事務(wù)的奇妙和隔離的重要,于是打算好好學(xué)習(xí)數(shù)據(jù)庫,不再看美女主播跳舞了。

圖片

而小帥,卻迷失在面向局子編程的路上越走越遠(yuǎn)。

4. 小結(jié)

我們總結(jié)一下,數(shù)據(jù)庫通過隔離級別解決了事務(wù)并發(fā)出現(xiàn)的各種問題:

  • RU,讀未提交解決了臟寫問題,但可能出現(xiàn)臟讀;
  • RC,讀已提交解決了臟讀問題,但可能出現(xiàn)不可重復(fù)讀;
  • RR,可重復(fù)讀解決了不可重復(fù)讀的問題,但可能出現(xiàn)幻讀;
  • Serializable,串行化解決了幻讀的問題,但性能很低。

MySQL 是怎么實(shí)現(xiàn)事務(wù)隔離性的呢?

答案是加鎖。事務(wù)級別越高,解決的并發(fā)事務(wù)問題越多,同時也意味著加的鎖就越多。

鎖的個數(shù)對比:RU-讀未提交 < RC-讀已提交 < RR-可重復(fù)讀 < Serializable-串行化。

但是,頻繁的加鎖可能會導(dǎo)致讀取數(shù)據(jù)的時候沒辦法修改,修改數(shù)據(jù)的時候沒辦法讀取,極大的降低了數(shù)據(jù)庫讀寫性能,就像串行化的隔離級別那樣。

所以,為了權(quán)衡數(shù)據(jù)安全和性能,MySQL 數(shù)據(jù)庫默認(rèn)使用的是 RR,即可重復(fù)讀的隔離級別。


責(zé)任編輯:武曉燕 來源: xin猿意碼
相關(guān)推薦

2025-04-28 09:27:26

2020-10-13 10:32:24

MySQL事務(wù)MVCC

2025-01-13 13:12:54

2018-12-19 16:46:38

MySQL事務(wù)隔離數(shù)據(jù)庫

2025-04-08 04:00:00

Linux內(nèi)核頁面回收

2025-04-21 04:00:00

2021-07-26 10:28:13

MySQL事務(wù)隔離

2024-04-26 09:17:20

MySQL事務(wù)隔離

2021-08-04 13:19:42

MySQL 事務(wù)隔離

2019-11-06 16:33:29

Ignite微軟技術(shù)

2021-09-07 10:33:42

MySQL事務(wù)隔離性

2024-12-02 08:37:04

2025-03-03 08:20:00

MySQL事務(wù)隔離數(shù)據(jù)庫

2025-03-28 09:19:11

2021-10-19 10:10:51

MySQL事務(wù)隔離級別數(shù)據(jù)庫

2024-05-10 09:31:22

務(wù)隔離級別Python

2020-09-21 18:44:35

MySQL

2019-10-15 10:23:13

服務(wù)器MySQL 數(shù)據(jù)

2017-08-09 14:34:12

MysqlJavaPython

2022-06-10 11:51:49

MySQL事務(wù)隔離
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號