數(shù)據(jù)庫(kù)事務(wù)基礎(chǔ)

一育八、為什么需要事務(wù)实檀?

舉個(gè)例子:
A 和 B 賬戶各有 50 元余額,現(xiàn)在 A 要給 B 轉(zhuǎn)賬 10 元,刨除掉具體的業(yè)務(wù)邏輯和工作流程豺旬,僅考慮數(shù)據(jù)庫(kù)層面的操作:A 賬戶-10,B 賬戶+10 。
如果沒(méi)有事務(wù),就只能讓兩個(gè) update 操作串行執(zhí)行:

// 代碼片段1
run("update account set balance=balance-10 where account_id=A");
run("update account set balance=balance+10 where account_id=B");
圖1

如圖1北启,對(duì)于這個(gè)轉(zhuǎn)賬操作场钉,我們的期望是:

  • 代碼片段1執(zhí)行前,數(shù)據(jù)庫(kù)數(shù)據(jù):A 余額 50,B 余額 50。
  • 代碼片段1執(zhí)行后,數(shù)據(jù)庫(kù)數(shù)據(jù):A 余額 40,B 余額 60。

但是,如果執(zhí)行完 A-10 后,系統(tǒng)崩潰了,B+10 沒(méi)能得到執(zhí)行。則:

  • 代碼片段1執(zhí)行前须蜗,數(shù)據(jù)庫(kù)數(shù)據(jù):A 余額 50菱农,B 余額50的妖。
  • 代碼片段1執(zhí)行后嫂粟,數(shù)據(jù)庫(kù)數(shù)據(jù):A 余額 40娇未,B 余額50。
  • 在此場(chǎng)景下星虹,對(duì) A 來(lái)說(shuō)忘蟹,這個(gè)轉(zhuǎn)賬操作是成功了的,畢竟錢(qián)都扣掉了搁凸,但 B 卻沒(méi)有收到對(duì)應(yīng)的款項(xiàng)媚值,也就是說(shuō)從 A 賬戶扣掉的 10 塊錢(qián)憑空消失了。這在實(shí)際業(yè)務(wù)中是不可接受的护糖。

要解決這個(gè)問(wèn)題褥芒,就必須有一套機(jī)制,來(lái)保證 A-10 和 B+10 這兩個(gè)操作同時(shí)成功嫡良,或同時(shí)失敗锰扶,以確保兩個(gè) update 操作執(zhí)行前后的數(shù)據(jù)的一致性、正確性和完整性寝受。

這套機(jī)制坷牛,就是“事務(wù)”。

二很澄、事務(wù)定義

數(shù)據(jù)庫(kù)事務(wù) 是可以作為一個(gè)完整的邏輯工作單元來(lái)執(zhí)行的不可分割的一組操作京闰,這些操作要么全部執(zhí)行,要么全部不執(zhí)行甩苛。

  • 在關(guān)系型數(shù)據(jù)庫(kù)中蹂楣,事務(wù)可以是一條sql語(yǔ)句,也可以是多條sql語(yǔ)句讯蒲。
  • 在此基礎(chǔ)之上痊土,為了保證這一組操作執(zhí)行結(jié)果的正確性和有效性,事務(wù)又附加了一些條件墨林,就是ACID了赁酝。

ACID 的關(guān)注點(diǎn)和對(duì)事務(wù)的要求如下:


ACID

一致?tīng)顟B(tài)犯祠,是指數(shù)據(jù)處于一種語(yǔ)義上的有意義且正確的狀態(tài)。
隔離性還有其他的稱呼酌呆,如:并發(fā)控制衡载、可串行化、鎖等肪笋。

三、事務(wù)并發(fā)問(wèn)題和隔離模式

并發(fā)訪問(wèn)場(chǎng)景下度迂,若沒(méi)有采取必要的隔離措施藤乙,會(huì)存在一些讀寫(xiě)問(wèn)題,包括:

  • 3 類數(shù)據(jù)讀問(wèn)題:臟讀惭墓、不可重復(fù)讀和幻讀坛梁。
  • 2 類數(shù)據(jù)更新問(wèn)題:第一類丟失更新、第二類丟失更新腊凶。
并發(fā)讀寫(xiě)問(wèn)題

數(shù)據(jù)庫(kù)提供不同級(jí)別的事務(wù)隔離模式划咐,解決部分或全部上述的讀寫(xiě)問(wèn)題,SQL 規(guī)范定義了四種級(jí)別的隔離模式(級(jí)別由低到高):

  1. Read Uncommitted(讀未提交):最低的隔離級(jí)別钧萍,什么都不需要做褐缠,一個(gè)事務(wù)可以讀到另一個(gè)事務(wù)未提交的結(jié)果。所有的并發(fā)事務(wù)問(wèn)題都會(huì)發(fā)生风瘦。
  2. Read Committed(讀已提交):只有在事務(wù)提交后队魏,其更新結(jié)果才會(huì)被其他事務(wù)看見(jiàn)⊥蛏Γ可以解決臟讀問(wèn)題胡桨。
  3. Repeated Read(可重復(fù)讀):在一個(gè)事務(wù)中,對(duì)于同一份數(shù)據(jù)的讀取結(jié)果總是相同的瞬雹,無(wú)論是否有其他事務(wù)對(duì)這份數(shù)據(jù)進(jìn)行操作昧谊,以及這個(gè)事務(wù)是否提交⌒锇疲可以解決臟讀呢诬、不可重復(fù)讀。
  4. Serialization(串行化):事務(wù)串行化執(zhí)行胖缤,最高隔離級(jí)別馅巷,犧牲系統(tǒng)的并發(fā)性,將所有事務(wù)串行執(zhí)行草姻〉鲡可以解決并發(fā)事務(wù)的所有問(wèn)題。

事務(wù)的隔離級(jí)別和數(shù)據(jù)庫(kù)并發(fā)性是成反比的撩独,隔離級(jí)別越高敞曹,并發(fā)性越低账月。

四、ACID的實(shí)現(xiàn)技術(shù)

ACID 的實(shí)現(xiàn)技術(shù)包括:并發(fā)控制澳迫、日志管理局齿、備份恢復(fù)、鎖管理橄登、MVCC等內(nèi)容抓歼。
其中,并發(fā)控制和日志技術(shù)是核心拢锹。

4.1 并發(fā)控制技術(shù)

并發(fā)控制技術(shù)是實(shí)現(xiàn)原子性谣妻、一致性和隔離性的重要技術(shù)之一。并發(fā)控制的本質(zhì)就是要對(duì)并發(fā)的事務(wù)實(shí)現(xiàn)正確又高效的調(diào)度卒稳。

從實(shí)現(xiàn)思想的角度看蹋半,并發(fā)控制技術(shù)分兩類:

  • 樂(lè)觀并發(fā)控制,Optimistic Concurrency Control充坑,OOC减江,事后檢查。
  • 悲觀并發(fā)控制捻爷,Pessimistic Concurrency Control辈灼,PCC,提前預(yù)防也榄。

從實(shí)現(xiàn)技術(shù)角度茵休,并發(fā)控制機(jī)制有如下幾類:

  1. 基于鎖的并發(fā)控制機(jī)制

基于鎖的并發(fā)控制機(jī)制是最常見(jiàn)的一種并發(fā)控制機(jī)制,事務(wù)中可能涉及到的一些鎖的概念如下圖:


  1. 基于時(shí)間戳/數(shù)據(jù)版本的并發(fā)控制

基于數(shù)據(jù)版本的并發(fā)訪問(wèn)控制手蝎,是通過(guò)給數(shù)據(jù)表加一個(gè)版本號(hào)或時(shí)間戳字段實(shí)現(xiàn)榕莺。

  • 當(dāng)讀取數(shù)據(jù)時(shí),將 version字段的值一同讀出棵介,數(shù)據(jù)每更新一次钉鸯,對(duì)此 version 值加一。
  • 當(dāng)提交更新的時(shí)候邮辽,判斷當(dāng)前版本信息與第一次取出來(lái)的版本值大小唠雕,如果數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào)與第一次取出來(lái)的 version 值相等,則予以更新吨述,否則認(rèn)為是過(guò)期數(shù)據(jù)岩睁,拒絕更新。

基于時(shí)間戳的并發(fā)控制類似揣云,把版本號(hào)換成時(shí)間戳就行了捕儒。

  1. 基于MVCC的并發(fā)控制

MVCC(Multi-Version Concurrent Control),即多版本并發(fā)控制協(xié)議,是個(gè)行級(jí)鎖的變種刘莹,它在普通讀情況下避免了加鎖操作阎毅,因此開(kāi)銷更低,同時(shí)在保證數(shù)據(jù)一致性的前提下点弯,提供一種高并發(fā)的訪問(wèn)性能扇调。

雖然不同數(shù)據(jù)庫(kù)或數(shù)據(jù)庫(kù)引擎對(duì) MVCC 的實(shí)現(xiàn)不同,但通常都是實(shí)現(xiàn)非阻塞讀抢肛,對(duì)于寫(xiě)操作只鎖定必要的行:

  • 第一種實(shí)現(xiàn)方式:將數(shù)據(jù)記錄的多個(gè)版本保存在數(shù)據(jù)庫(kù)中狼钮,當(dāng)這些不同版本數(shù)據(jù)不再需要時(shí),垃圾回收器回收這些記錄捡絮“疚撸——PostgreSQL 和 Firebird/Interbase 采用。
  • 第二種實(shí)現(xiàn)方式:只在數(shù)據(jù)庫(kù)保存最新版本的數(shù)據(jù)锦援,但是會(huì)在使用undo時(shí)動(dòng)態(tài)重構(gòu)舊版本數(shù)據(jù)猛蔽“颍——Oracle 和 MySQL/InnoDB 采用灵寺。

4.2 日志技術(shù)

數(shù)據(jù)庫(kù)的日志可以大體分為3類:binlog区岗、redo log、undo log叮称。

其中,binlog是Server層記錄的日志藐鹤, redo log 和 undo log 是數(shù)據(jù)庫(kù)存儲(chǔ)引擎層的日志瓤檐。

大部分關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)是通過(guò) redo log 和 undo log 來(lái)實(shí)現(xiàn)事務(wù)的原子性娱节、一致性和持久性,同時(shí)也用于支持?jǐn)?shù)據(jù)備份和恢復(fù):

  • redo log肄满,記錄數(shù)據(jù)被修改后的值谴古,可以用來(lái)恢復(fù)未寫(xiě)入 data file 的已成功事務(wù)更新的數(shù)據(jù)。redo log 又包括:redo log buffer 和 redo log file稠歉,一個(gè)寫(xiě)內(nèi)存,一個(gè)寫(xiě)硬盤(pán)带饱。
  • undo log,記錄數(shù)據(jù)被修改前的值纠炮,可以用來(lái)在事務(wù)失敗時(shí)進(jìn)行 rollback。

舉個(gè)例子恢口,假設(shè) A=1且 B=2,某事務(wù) T 要做 A=3 和 B=4因妇,則

  1. 事務(wù)簡(jiǎn)化過(guò)程:
1.start
2.A=1——>undo log
3.set A=3
4.A=3——>redo log buffer
5.B=2——>undo log
6.set B=4
7.B=4——>redo log buffer
8.redo log buffer——>redo log file
9.commit
  1. undo 和 redo 日志:
// undo日志:
<T,A,1>
<T,B,2>
// redo日志:
<T,A,3>
<T,B,4>
  1. 數(shù)據(jù)恢復(fù)(重做猿诸、撤銷)
    若執(zhí)行 9 時(shí)出現(xiàn)系統(tǒng)異常,則下次啟動(dòng)時(shí)可以通過(guò) redo log 重做該事務(wù)梳虽。
    若執(zhí)行 6 時(shí)出現(xiàn)異常,則可以通過(guò) undo log 撤銷已經(jīng)做過(guò)的修改谷炸。
  2. undo/redo日志
    也有把 undo 和 redo 結(jié)合起來(lái)的做法禀挫,叫做 Undo/Redo 日志,在前面中的例子
    Undo/Redo 日志為:
<T, A, 1, 3>
<T, B, 2, 4>

五语婴、參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末砰左,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缠导,更是在濱河造成了極大的恐慌廉羔,老刑警劉巖酬核,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嫡意,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)此迅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)耸序,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人坎怪,你說(shuō)我怎么就攤上這事〗亮” “怎么了男应?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)沐飘。 經(jīng)常有香客問(wèn)我,道長(zhǎng)借卧,這世上最難降的妖魔是什么隔箍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任脚乡,我火速辦了婚禮,結(jié)果婚禮上俯艰,老公的妹妹穿的比我還像新娘锌订。我一直安慰自己,他們只是感情好辆飘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布蜈项。 她就那樣靜靜地躺著,像睡著了一般紧卒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轴总,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音功偿,去河邊找鬼往堡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛投蝉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播关拒,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼庸娱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了归露?” 一聲冷哼從身側(cè)響起斤儿,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎往果,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體堕油,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肮之,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年戈擒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峦甩。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖犬辰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灸促,我是刑警寧澤涵卵,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站轿偎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏萝玷。R本人自食惡果不足惜昆婿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望睁冬。 院中可真熱鬧看疙,春花似錦豆拨、人聲如沸狼荞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至斯碌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間投慈,已是汗流浹背承耿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工加袋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抱既,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓蚀之,卻偏偏與公主長(zhǎng)得像捷泞,于是被迫代替她去往敵國(guó)和親足删。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锁右,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容