1. 程式人生 > >MySQL 筆記整理(2) --日誌系統,一條SQL查詢語句如何執行

MySQL 筆記整理(2) --日誌系統,一條SQL查詢語句如何執行

發生 重要 表示 優勢 兩層 一秒 正在 引擎 http

筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》

2) --日誌系統,一條SQL查詢語句如何執行

  MySQL可以恢復到半個月內任意一秒的狀態,它的實現和日誌系統有關。上一篇中記錄了一條查詢語句是如何執行的,對於更新語句,這一套流程也是同樣會走一遍。與查詢流程不一樣的是,更新流程還涉及到兩個重要的日誌模塊。redo log(重做日誌) 和 binlog(歸檔日誌)。

redo log:

  這裏林老師舉了一個很好的例子,摘錄如下。

  《孔乙己》中的酒店掌櫃有一個粉板,用來記錄客人的賒賬記錄。如果賒賬的人不多,他可以把顧客名和賬目寫在粉板上。如果賒賬的人太多,粉板寫不下了,掌櫃的還會有一個專門記錄賒賬的賬本。如果有人要賒賬或者還賬的話,掌櫃的一般有兩種做法:

    1. 一種做法是直接把賬本翻出來,把這次賒賬的記錄加上去或者除掉。
    2. 另一種做法是先再粉板上記下這次的賬,等打烊以後再把賬本翻出來核算。

  如果客人太多,掌櫃的一定會選擇後者,因為前者的操作實在是太麻煩了。要在賬本上翻上個幾十頁再一條條的查找,然後再用算盤計算。相比之下,在粉板上記錄下來就簡單的多。

  同樣,在MySQL裏也會有這個問題。如果每次更新操作都要寫進磁盤,然後磁盤也要找到對應的那條記錄,然後再更新,整個過程IO成本及查找成本都很高。

  1. MySQL中這種類似粉板和賬本配合的過程就是WAL技術(Write-Ahead Logging)它的關鍵點是先寫日誌,再寫磁盤。
  2. 當一條記錄需要更新時,InnoDB引擎就會先把記錄寫到redo log裏面,並更新內存(粉板)。同時,InnoDB引擎會在適當的時候將他更新到磁盤裏(賬單)。
  3. redo log的大小是固定。因此如果系統繁忙,redo log很快就會寫滿。此時就不得不先把一部分記錄更新到磁盤裏,然後再進行後續的寫入。
  4. 有了redo log, InnoDB就可以保證記錄不會丟失,這個能力稱為 crash-safe。(掌櫃把記錄寫入了粉板,沒寫入賬單。晚上掌櫃的忘記這件事了(DB異常重啟),一看粉板(redo log)也可以重新寫入賬單)

binlog:

  1. 之前提到過MySQL分為兩層,一是Server層,另一個是引擎層。redo log是InnoDB引擎特有的日誌
    ,而Server層也有自己的日誌,成為binlog(歸檔日誌)
  2. redo log 與 binlog 有三點不同:
  • redo log是InnoDB引擎特有的日誌,binlog是MySQL的Server層實現,所有引擎都可以使用。
  • redo log是物理日誌,記錄的是“在某個數據頁上做了什麽操作”;binlog是邏輯日誌,記錄是語句的原始邏輯,比如“給ID=2這一行的c字段加1”.
  • redo log大小固定,循環寫入。binlog可以追加寫,不會覆蓋以前的日誌。

兩階段提交:

技術分享圖片

(圖片來源於 極客時間 林曉斌 《MySQL 實戰45講》,如有版權問題請聯系我刪除)

  可以看到最後一部分把redo log拆成了兩部分,prepare和commit,這就是“兩階段”提交。

  關於兩階段提交,如果不這樣做的話則上述過程會演變成先寫完redo log或者先寫完binlog,假設在寫完一個log,正在寫第二個log時發生異常

  1. 先寫redo log:前面有提到,由於redo log已經寫完,仍能將redo log中的數據恢復回來。但由於binlog中沒有這個記錄,所以當你使用binlog來恢復臨時庫時,臨時庫便會少一次邏輯上的更新,即臨時庫認為沒有這次的更新,故與原數據不同。
  2. 先寫binlog:由於binlog已經寫完,恢復臨時庫時會執行這次的操作,但redo log中並沒有相關記錄,這個事務無效也無法恢復,與=原數據不同。

另:innodb_flush_log_at_trx_commit這個參數設置為1表示把redo log直接持久化到磁盤,保證mysql異常重啟之後數據不丟失。

sync_binlog設置為1時表示binlog持久化到磁盤,保證mysql異常重啟後binlog不丟失。

上篇問題答案:

如果表T中沒有字段k,而去執行這個語句 select * from T where k = 1,那麽會報錯“Unknown column ‘k’ in ‘where clause’”。請問這個錯誤是在哪個階段報出的?

答案是 分析器。筆記中有暗示啦,

分析器:分析器會先做“詞法分析”,即從你輸入的"select"這個關鍵字識別出來這是一個查詢語句,把你輸入的字符串“ID”識別成“列ID”。之後會進行“語法分析”,判斷你輸入的sql語句是否滿足語法規則。

問題:

請問在什麽場景下,一天一次備份會比一周一次備份更有優勢?或者說,它影響了這個數據系統的哪些指標?

MySQL 筆記整理(2) --日誌系統,一條SQL查詢語句如何執行