1. 程式人生 > >跟面試官侃半小時MySQL事務,說完原子性、一致性、永續性的實現

跟面試官侃半小時MySQL事務,說完原子性、一致性、永續性的實現

提到MySQL的事務,我相信對MySQL有了解的同學都能聊上幾句,無論是面試求職,還是日常開發,MySQL的事務都跟我們息息相關。

而事務的ACID(即原子性Atomicity、一致性Consistency、隔離性Isolation、永續性Durability)可以說涵蓋了事務的全部知識點,所以,我們不僅要知道ACID是什麼,還要了解ACID背後的實現,只有這樣,無論在日常開發還是面試求職,都能無往而不利。

上一篇 跟面試官侃半小時MySQL事務隔離性,從基本概念深入到實現 主要圍繞“隔離性”展開,從基本概念,到隔離性的實現,最後以一個實戰案例進行融會貫通。本篇內容將介紹原子性、一致性、永續性相關實現,由於這部分內容可能很多人會相對陌生,因為日常業務開發可能不太會去接觸和深究,但是瞭解完後,你對MySQL會有更深刻的認識。

1.基本概念

  • 原子性。

整個事務是不可分割的最小單位,事務中任何一個語句執行失敗,所有已經執行成功的語句也要回滾,整個資料庫狀態要恢復到執行事務前到狀態。

  • 一致性。

事務將資料庫從一種狀態轉變為下一種一致的狀態。在事務的前後,資料庫的完整性約束沒有被破壞。(事務的acid不是完全正交的,尤其是一致性,可能跟原子性、隔離性都有一定關係,後面會看到)

  • 永續性。

事務一旦提交,那麼就是永久性的,不會因為宕機等故障導致資料丟失(外力影響不保證,比如磁碟損害)。永續性是保證了資料庫的高可靠性(High Reliability),而不是高可用性(Hign Availability)。高可用性並不能通過事務來保證。

2.永續性的實現

MySQL的innoDB儲存引擎,使用Redo log保證了事務的永續性。

當事務提交時,必須先將事務的所有日誌寫入日誌檔案進行持久化,就是我們常說的WAL(write ahead log)機制(這個技術是保障永續性的關鍵技術,在HBase中也扮演重要角色,有興趣的同學可以參考我之前關於HBase的文章)。這樣才能保證斷電或宕機等情況發生後,已提交的事務不會丟失,這個能力稱為 crash-safe。

下面深入聊一聊redo log的機制,給大家更深刻的理解。

Redo log包括兩部分,重做日誌緩衝(redo log buffer)和重做日誌檔案(redo log file),前者是易失的快取,後者是持久化的檔案。

舉一個事務的例子:

  • 步驟1:begin;
  • 步驟2:insert into t1 …r
  • 步驟3:insert into t2 …
  • 步驟4:commit;

這個事務的寫入過程實際拆解如下:

 

innodb緩衝池的概念本文就不展開說明了,以後有機會可以展開說一下。

重點關注在這個事務提交前,將 redo log 的寫入拆成了兩個步驟,prepare 和 commit,這就是"兩階段提交”。

為什麼要採用兩階段提交呢?

實際上,兩階段提交是分散式系統常用的機制。MySQL使用了兩階段提交後,也是為了保證事務的永續性。Redo log 和bingo 有一個共同的資料欄位,叫 XID,崩潰恢復的時候,會按順序掃描 redo log。

  • 假設在寫入binlog前系統崩潰,那麼資料庫恢復後順序掃描 redo log,碰到只有 parepare、而沒有 commit 的 redo log,就拿著 XID 去 binlog 找對應的事務,而且binlog也沒寫入,所以事務就直接回滾了。
  • 假設在寫入binlog之後,事務提交前資料庫崩潰,那麼資料庫恢復後順序掃描 redo log,碰到既有 prepare、又有 commit 的 redo log,就直接提交,保證資料不丟失。

這個事務要往兩個表中插入記錄,插入資料的過程中,生成的日誌都得先寫入redo log buffer ,等到commit的時候,才真正把日誌寫到 redo log 檔案。(當然,這裡不絕對,因為redo log buffer可能因為其他原因被迫重新整理到redo log)。

而為了確保每次日誌都能寫入日誌檔案,在每次將重做日誌緩衝 寫入 重做日誌檔案 後,InnoDB儲存引擎都需要呼叫一次fsync操作,確保寫入了磁碟。

對於redo log的持久化,可以如下圖所示。

 

1)先寫入redo log buffer,在藍色區域。

2)寫入redo log file,但是還沒有fsync,這時候是處於黃色的位置,處於系統快取。

3)呼叫fsync,真正寫入磁碟。

為了控制 redo log 的寫入策略,InnoDB 提供了 innodb_flush_log_at_trx_commit 引數,它有三種可能取值:

  • 設定為 0 的時候,表示每次事務提交時都只是把 redo log 留在 redo log buffer 中 ;
  • 設定為 1 的時候,表示每次事務提交時都將 redo log 直接持久化到磁碟;
  • 設定為 2 的時候,表示每次事務提交時都只是把 redo log 寫到 page cache。

binlog的寫入和redo log一樣,也是包括bingo cache和bingo file,同樣跟上面的三色層次類似(當然,binlog是server層的,不是儲存引擎層的),包括log buffer、檔案系統page cache、hard disk。

寫入page cache 和 fsync到disk 的時機,是由引數 sync_binlog 控制的:

  • sync_binlog=0 的時候,表示每次提交事務都只 寫入檔案系統的page cache,不 fsync;
  • sync_binlog=1 的時候,表示每次提交事務都會執行 fsync;
  • sync_binlog=N(N>1) 的時候,表示每次提交事務都寫入檔案系統的page cache,但累積 N 個事務後才 fsync。(如果主機發生異常重啟,會丟失最近 N 個事務的 binlog 日誌)

通常我們說 MySQL 的“雙 1”配置,指的就是 sync_binlog 和 innodb_flush_log_at_trx_commit 都設定成 1。也就是說,一個事務完整提交前,需要等待兩次刷盤,一次是 redo log(prepare 階段),一次是 binlog。

特別需要區分的是,redo log和binlog的不同。這也是經常在面試中可能會問到的兩種日誌的差異。

注意有這麼幾點:

  • 產生位置不同。

redo log是innodb的儲存引擎產生的,而binlog是資料庫的server層實現的。換句話說,如果你使用MySQL,換其他儲存引擎,那麼可能沒有redo log,但是還是會有binlog。

  • 日誌記錄的內容形式不同。

binlog是一種邏輯日誌,記錄對應的SQL語句,而redo log記錄了物理日誌,是針對每個資料頁的修改。

  • 日誌寫入磁碟時間不同。

binlog只有在事務提交後完成一次寫入,對於一個事物而言,在binlog中只有一條記錄。而redo log在事務進行中不斷被寫入,而且是併發寫入的,不是順序寫入的。

 

  • 儲存方式不同。

redo log 是迴圈寫的,空間固定會用完;binlog 是可以追加寫入的。“追加寫”是指 binlog 檔案寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。

3.原子性的實現

Undo log保證了事務的原子性。

在對資料庫進行修改時,innoDB引擎除了會產生redo log,還會產生undo log。InnoDB實現回滾,靠的是undo log:當事務對資料庫進行修改時,InnoDB會生成對應的undo log;如果事務執行失敗導致事務需要回滾,就利用undo log中的資訊將資料回滾到修改之前的樣子。

有人認為undo log是redo log的逆過程,其實是不對的。兩個日誌檔案其實都能看作是一種對資料的恢復操作,redo log恢復事務導致的資料頁的修改,而undo log能夠恢復資料記錄到某個特定的版本。

所以redo log是一種物理日誌(資料頁的修改),而undo log是一種邏輯日誌(資料記錄)。

undo log還要另外一個重要作用,就是用於mvcc中,進行多版本控制,也就是實現事務隔離性的基礎,當用戶讀取一行記錄時,如果這個記錄已接被其他事務佔用,那麼當前事務就可以通過undo讀取之前的行版本資訊,用來實現非鎖定讀取,就是“快照讀”。(事務隔離性的問題,可以看我上一篇文章 跟面試官侃半小時MySQL事務隔離性,從基本概念深入到實現 )。

4.一致性的實現

就像一開始在定義的時候介紹的,事務的ACID性質不是完全正交的,尤其是一致性,我們可以認為原子性、永續性和隔離性都是為了實現事務的一致性。

當然,這裡的一致性是指資料庫層面的事務一致性。

如果說你在應用層面做一個操作,給轉賬者扣錢,沒給接收者加錢,那麼這個不一致跟事務的不一致是沒有關係的,需要開發人員自己做業務邏輯一致性的保證。

 

看到這裡了,原創不易,點個關注、點個贊吧,你最好看了~

知識碎片重新梳理,構建Java知識圖譜:https://github.com/saigu/JavaKnowledgeGraph(歷史文章查閱非常方便)

掃碼關注我的公眾號“阿丸筆記”,第一時間獲取最新更新。同時可以免費獲取海量Java技術棧電子書、各個大廠面試題。

相關推薦

面試小時MySQL事務原子一致性永續性實現

提到MySQL的事務,我相信對MySQL有了解的同學都能聊上幾句,無論是面試求職,還是日常開發,MySQL的事務都跟我們息息相關。 而事務的ACID(即原子性Atomicity、一致性Consistency、隔離性Isolation、永續性Durability)可以說涵蓋了事務的全部知識點,所以,我們不僅要知

面試小時MySQL事務隔離從基本概念深入到實現

提到MySQL的事務,我相信對MySQL有了解的同學都能聊上幾句,無論是面試求職,還是日常開發,MySQL的事務都跟我們息息相關。 而事務的ACID(即原子性Atomicity、一致性Consistency、隔離性Isolation、永續性Durability)可以說涵蓋了事務的全部知識點,所以,我們不僅要知

騰訊面試居然我扯了小時的CountDownLatch

一個長頭髮、穿著清爽的小姐姐,拿著一個嶄新的Mac筆記本向我走來,看著來勢洶洶,我心想著肯定是技術大佬吧!但是我也是一個才華橫溢的人,穩住我們能贏。 ![面試官](https://img-blog.csdnimg.cn/20200509090547451.jpeg#pic_center) > **面試官**

頭條面試居然我扯了小時的Semaphore

一個長頭髮、穿著清爽的小姐姐,拿著一個嶄新的Mac筆記本向我走來,看著來勢洶洶,我心想著肯定是技術大佬吧!但是我也是一個才華橫溢的人,穩住我們能贏。 ![](https://img-blog.csdnimg.cn/20200607091134202.png#pic_center) > **面試官**:看你

一個HashMap能面試扯上半個小時

### 一個HashMap能跟面試官扯上半個小時 > 《安琪拉與面試官二三事》系列文章 > [一個HashMap能跟面試官扯上半個小時](https://blog.csdn.net/zhengwangzw/article/details/104889549) > [一個synchroniz

## 【分散式事務面試問我:MySQL中的XA事務崩潰瞭如何恢復??

## 寫在前面 > 前段時間搭建了一套MySQL分散式資料庫叢集,資料庫節點有12個,用來測試各種分散式事務方案的效能和優缺點。測試MySQL XA事務時,正當測試指令碼向資料庫中批量插入資料時,強制伺服器斷電!注意:是直接拔電源,使其瞬間斷電,再次重啟伺服器後,MySQL資料庫報錯了。特此記錄MyS

Mysql資料處理按照小時彙總資料

需求:將資料庫中每分鐘一條的資料表,從9:30取到22:00 ,以半小時為單位彙總,並輸出excel。 資料表字段:id(序號)、incount(計數)、cdate(資料時間) 表名:m_temp 難點:時間處理 解決辦法:使用DATE_FORMAT、CONCAT、Date、Ho

面試講Binder(二)之關於AIDL的認識

面試官開口說:“聽你剛才所說,在Android系統中,都是利用Binder來進行程序間通訊的,那我怎麼聽說,還有利用AIDL來實現程序間通訊的呢?”。 其實,AIDL只是一種描述性語言,其全稱是Android Interface Definition Language,即介

面試問“為什麼選擇mysql資料庫”說開去

前幾天面試,面試官問我:“為什麼選擇mysql資料庫”。現在想想,有如下的問題需要解決 關係型資料庫有什麼特點及舉例 非關係型資料庫有什麼特點及舉例 關係型資料庫與非關係型資料庫有什麼區別 關係型資

這篇HTTP面試扯皮就沒問題了

我是一名程式設計師,我的主要程式語言是 Java,我更是一名 Web 開發人員,所以我必須要了解 HTTP,所以本篇文章就來帶你從 HTTP 入門到進階,看完讓你有一種恍然大悟、醍醐灌頂的感覺。 最初在有網路之前,我們的電腦都是單機的,單機系統是孤立的,我還記得 05 年前那會兒家裡有個電腦,想打電腦遊戲還得

【原創】面試:談談你對mysql聯合索引的認識?

引言 本文預計分為兩個部分: (1)聯合索引部分的基礎知識 在這個部分,我們溫習一下聯合索引的基礎 (2)聯合索引部分的實戰題 在這個部分,列舉幾個我認為算是實戰中的代表題,挑出來說說。 正文 基礎 講聯合索引,一定要扯最左匹配!放心,我不扯有的沒的,幾句話懂個大概就行! 最左匹配 所謂最左原則指的就是如果你

這個案例寫出來還怕面試扯不明白 OAuth2 登入流程?

昨天和小夥伴們介紹了 OAuth2 的基本概念,在講解 Spring Cloud Security OAuth2 之前,我還是先來通過實際程式碼來和小夥伴們把 OAuth2 中的各個授權模式走一遍,今天我們來看最常用也最複雜的授權碼模式。 本文我將通過一個完整的 Demo ,注意,是一個完整的 Demo,帶領

面試:你知道哪些事務失效的場景?

前言 宣告式事務是Spring功能中最爽之一,可是有些時候,我們在使用宣告式事務並未生效,這是為什麼呢? 文章首發於微信公眾號【碼猿技術專欄】 今天陳某帶大家來聊一聊宣告事務的幾種失效場景。本文將會從以下兩個方面來說一下事務為什麼會失效? @Transactional介紹 @Transactional失效場

面試突然問我MySQL儲存過程我竟然連基礎都不會!(詳細)

**所有知識體系文章,[GitHub](https://github.com/Ziphtracks/JavaLearningmanual)已收錄,歡迎Star!再次感謝,願你早日進入大廠!** **GitHub地址:** [https://github.com/Ziphtracks/JavaLearning

這篇 HashSet面試扯皮沒問題了

> 我是風箏,公眾號「古時的風箏」,一個兼具深度與廣度的程式設計師鼓勵師,一個本打算寫詩卻寫起了程式碼的田園碼農! 文章會收錄在 [JavaNewBee](https://github.com/huzhicheng/JavaNewBee) 中,更有 Java 後端知識圖譜,從小白到大牛要走的路都在裡面。 之

MySQL面試問我:MySQL如何實現無資料插入有資料更新?我是這樣回答的!

## 寫在前面 > 馬上就是金九銀十的跳槽黃金期了,很多讀者都開始出去面試了。這不,又一名讀者出去面試被面試官問了一個MySQL的問題:向MySQL中插入資料,如何實現MySQL中沒有當前id標識的資料時插入資料,有當前id標識的資料時更新資料。其實,這題目一點也不難!! ## 先來個簡單題目 正

Mysql事務並發問題鎖機制

記錄 其中 什麽是 原子性 結果 內部 個數 執行 處理 1、什麽是事務 事務是一條或多條數據庫操作語句的組合,具備ACID,4個特點。 原子性:要不全部成功,要不全部撤銷 隔離性:事務之間相互獨立,互不幹擾 一致性:數據庫正確地改變狀態後,數據庫的一致性約束沒有被破壞 持

事務2 mysql事務

mysql事務隔離級別 髒讀 事務A讀取了事務B更新的資料,然後B回滾操作,那麼A讀取到的資料是髒資料 不可重複讀 事務 A 多次讀取同一資料,事務 B 在事務A多次讀取的過程中,對資料

事務1mysql事務分散式事務雜記1

定義 單個邏輯單元執行一組操作,要麼成功要麼失敗 特性 原子工作單元 對資料修改要麼執行要麼不執行 一致性 從一個一致狀態到另一個一致狀態

面試複習系列】常用機器學習演算法知識點及其解析面試會考的幾乎都有歡迎補充

圖片慢慢上傳,看不到圖片的請點這裡: LR:logistic regression  對數機率迴歸/邏輯迴歸 sigmoid函式的作用就是用於把輸出歸一到1和0,也就