Mysql 事務是怎麼實現的

在前一陣子,大哥問過我:」你知道MySQL的原子性是怎麼保證的嗎「。我懵逼了,MySQL怎麼保證原子性?我不會啊。java

誰都知道在事務裏邊原子性的意思:」一個事務包含多個操做,這些操做要麼所有執行,要麼全都不執行面試

因而大哥就給我講:」用的就是 undo log 啊「。sql

我:」臥槽,又是知識盲區「數據庫

後來在網上翻了一下,MySQL裏邊還有幾種常見的log,分別爲:服務器

  • undo log
  • binlog
  • redo log

若是你也不曾關注過這些log,麻煩在評論區給我留個言,讓我以爲不是隻有我一我的這麼菜,行不行搜索引擎

後來我又去搜了一下,其實這幾種log在面試的時候也常常會問到,這篇文章以最簡單的方式來說講,但願對你們有幫助。版本控制

1、什麼是binlog

binlog其實在平常的開發中是聽得不少的,由於不少時候數據的更新就依賴着binlog日誌

舉個很簡單的例子:咱們的數據是保存在數據庫裏邊的嘛,如今咱們對某個商品的某個字段的內容改了(數據庫變動),而用戶檢索的出來數據是走搜索引擎的。爲了讓用戶能搜到最新的數據,咱們須要把引擎的數據也改掉。code

一句話:數據庫的變動,搜索引擎的數據也須要變動blog

因而,咱們就會監聽binlog的變動,若是binlog有變動了,那咱們就須要將變動寫到對應的數據源。

什麼是binlog

binlog記錄了數據庫表結構和表數據變動,好比update/delete/insert/truncate/create。它不會記錄select(由於這沒有對錶沒有進行變動)

binlog長什麼樣?

binlog咱們能夠簡單理解爲:存儲着每條變動的SQL語句(固然從下面的圖看來看,不止SQL,還有XID「事務Id」等等)

binlog通常用來作什麼

主要有兩個做用:複製和恢復數據

  • MySQL在公司使用的時候每每都是一主多從結構的,從服務器須要與主服務器的數據保持一致,這就是經過binlog來實現的
  • 數據庫的數據被幹掉了,咱們能夠經過binlog來對數據進行恢復。

由於binlog記錄了數據庫表的變動,因此咱們能夠用binlog進行復制(主從複製)和恢復數據。

2、什麼是redo log

假設咱們有一條sql語句:

update user_table set name='java3y' where id = '3'

MySQL執行這條SQL語句,確定是先把id=3的這條記錄查出來,而後將name字段給改掉。這沒問題吧?

實際上Mysql的基本存儲結構是(記錄都存在頁裏邊),因此MySQL是先把這條記錄所在的找到,而後把該頁加載到內存中,在內存中對數據進行修改,再刷回磁盤上。

如今就可能存在一個問題:若是在內存中把數據改了,還沒來得及落磁盤,而此時的數據庫忽然宕機怎麼辦?顯然此次更改就丟了。

怎麼解決這個問題?

簡單啊,事務提交前直接把數據寫入磁盤就行啊。

這麼作有什麼問題?

只修改一個頁面裏的一個字節,就要將整個頁面刷入磁盤,太浪費資源了。畢竟一個頁面16kb大小,你只改其中一點點東西,就要將16kb的內容刷入磁盤,聽着也不合理。

畢竟一個事務裏的SQL可能牽涉到多個數據頁的修改,而這些數據頁可能不是相鄰的,也就是屬於隨機IO。顯然操做隨機IO,速度會比較慢,MySQL可能也頂不住。因此MySQL是怎麼作的呢?

MySQL引入了redo log,當作數據修改的時候,不只在內存中操做,還會在redo log中記錄此次操做。當事務提交的時候,會將redo log日誌進行刷盤(redo log一部分在內存中,一部分在磁盤上)。當數據庫宕機重啓的時候,會將redo log中的內容恢復到數據庫中,再根據undo log和binlog內容決定回滾數據仍是提交數據。

其實寫redo log的時候,也會有buffer,是先寫buffer,再真正落到磁盤中的。至於從buffer何時落磁盤,會有配置供咱們配置。

redo log也是須要寫磁盤的,但它的好處就是順序IO(咱們都知道順序IO比隨機IO快很是多)。

因此,redo log的存在爲了:當咱們修改的時候,寫完內存了,但數據還沒真正寫到磁盤的時候。此時咱們的數據庫掛了,咱們能夠根據redo log來對數據進行恢復。由於redo log是順序IO,因此寫入的速度很快,而且redo log記載的是物理變化(xxxx頁作了xxx修改),文件的體積很小,恢復速度很快

3、binlog和redo log

看到這裏,你可能會想:binlogredo log 這倆也太像了吧,都是用做」恢復「的。

其實他倆除了"恢復"這塊是類似的,不少都不同,下面看我列一下。

存儲的內容

binlog記載的是update/delete/insert這樣的SQL語句,而redo log記載的是物理修改的內容(xxxx頁修改了xxx)。

因此在搜索資料的時候會有這樣的說法:redo log 記錄的是數據的物理變化binlog記錄的是數據的邏輯變化

功能

redo log的做用是爲持久化而生的。寫完內存,若是數據庫掛了,那咱們能夠經過redo log來恢復內存還沒來得及刷到磁盤的數據,將redo log加載到內存裏邊,那內存就能恢復到掛掉以前的數據了。

binlog的做用是複製和恢復而生的。

  • 主從服務器須要保持數據的一致性,經過binlog來同步數據。
  • 若是整個數據庫的數據都被刪除了,binlog存儲着全部的數據變動狀況,那麼能夠經過binlog來對數據進行恢復。

又看到這裏,你會想:」若是整個數據庫的數據都被刪除了,那我能夠用redo log的記錄來恢復嗎?「不能

由於功能的不一樣,redo log 存儲的是物理數據的變動,若是咱們內存的數據已經刷到了磁盤了,那redo log的數據就無效了。因此redo log不會存儲着歷史全部數據的變動,文件的內容會被覆蓋的

binlog和redo log 寫入的細節

redo log是MySQL的InnoDB引擎所產生的。

binlog不管MySQL用什麼引擎,都會有的。

InnoDB是有事務的,事務的四大特性之一:持久性就是靠redo log來實現的(若是寫入內存成功,但數據還沒真正刷到磁盤,若是此時的數據庫掛了,咱們能夠靠redo log來恢復內存的數據,這就實現了持久性)。

上面也提到,在修改的數據的時候,binlog會記載着變動的類容,redo log也會記載着變動的內容。(只不過一個存儲的是物理變化,一個存儲的是邏輯變化)。那他們的寫入順序是什麼樣的呢?

redo log事務開始的時候,就開始記錄每次的變動信息,而binlog是在事務提交的時候才記錄。

因而新有的問題又出現了:我寫其中的某一個log,失敗了,那會怎麼辦?如今咱們的前提是先寫redo log,再寫binlog,咱們來看看:

  • 若是寫redo log失敗了,那咱們就認爲此次事務有問題,回滾,再也不寫binlog
  • 若是寫redo log成功了,寫binlog,寫binlog寫一半了,但失敗了怎麼辦?咱們仍是會對此次的事務回滾,將無效的binlog給刪除(由於binlog會影響從庫的數據,因此須要作刪除操做)
  • 若是寫redo logbinlog都成功了,那此次算是事務纔會真正成功。

簡單來講:MySQL須要保證redo logbinlog數據是一致的,若是不一致,那就亂套了。

  • 若是redo log寫失敗了,而binlog寫成功了。那假設內存的數據還沒來得及落磁盤,機器就掛掉了。那主從服務器的數據就不一致了。(從服務器經過binlog獲得最新的數據,而主服務器因爲redo log沒有記載,無法恢復數據)
  • 若是redo log寫成功了,而binlog寫失敗了。那從服務器就拿不到最新的數據了。

MySQL經過兩階段提交來保證redo logbinlog的數據是一致的。

過程:

  • 階段1:InnoDBredo log 寫盤,InnoDB 事務進入 prepare 狀態
  • 階段2:binlog 寫盤,InooDB 事務進入 commit 狀態
  • 每一個事務binlog的末尾,會記錄一個 XID event,標誌着事務是否提交成功,也就是說,恢復過程當中,binlog 最後一個 XID event 以後的內容都應該被 purge。

4、什麼是undo log

undo log有什麼用?

undo log主要有兩個做用:回滾和多版本控制(MVCC)

在數據修改的時候,不只記錄了redo log,還記錄undo log,若是由於某些緣由致使事務失敗或回滾了,能夠用undo log進行回滾

undo log主要存儲的也是邏輯日誌,好比咱們要insert一條數據了,那undo log會記錄的一條對應的delete日誌。咱們要update一條記錄時,它會記錄一條對應相反的update記錄。

這也應該容易理解,畢竟回滾嘛,跟須要修改的操做相反就好,這樣就能達到回滾的目的。由於支持回滾操做,因此咱們就能保證:「一個事務包含多個操做,這些操做要麼所有執行,要麼全都不執行」。【原子性】

由於undo log存儲着修改以前的數據,至關於一個前版本,MVCC實現的是讀寫不阻塞,讀的時候只要返回前一個版本的數據就好了。

最後

這篇文章把binlog /redo log/undo log最核心的知識給講了,還有一些細節性的東西能夠自行去補充(好比binlog有幾種的模式,以及文章提到的刷盤策略等等)

轉自:java3y https://mp.weixin.qq.com/s/0z6GmUp0Lb1hDUo0EyYiUg 

相關文章
相關標籤/搜索