天天看點

一條MySQL更新語句是如何執行的?

查詢語句更新流程

更新流程前邊和查詢一樣也要走一遍查詢,因為更新之前必須拿到(查詢)更新的資料,先上一張流程圖,然後看詳細閱讀下面的各個步驟。

一條MySQL更新語句是如何執行的?

mysql執行流程圖

執行流程:

1.「連接配接驗證」

需要MySQL用戶端登入,需要一個 連接配接器 來連接配接使用者和MySQL資料庫,“mysql -u 使用者名 -p 密碼” 進行MySQL登入,在完成 TCP握手 後,連接配接器會根據輸入的使用者名和密碼驗證登入身份。

MySQL服務端和用戶端的通信方式采用的是「半雙工協定」。通信的時候,資料可以雙向傳輸,但是同一時間隻能有一台伺服器在發送資料。

2.「查詢緩存」

mysql8之後就去掉了查詢緩存,因為太雞肋了。當資料表發生修改時,涉及到這個表的查詢緩存都會失效。這可能導緻過多的緩存失效,并引發不一緻的資料查詢結果。

可以用過sql檢視查詢緩存是否開啟。

SHOW VARIABLES LIKE 'query_cache_type';
           

3.「分析器」

文法此法分析,在這裡首先會把整個sql打碎,并且能夠識别關鍵字和非關鍵字,根據sql語句生成一個資料結構,也叫做解析樹。

4.「預處理」

檢查表名和字段名等相關資訊合法性。

5.「優化器」

根據解析樹生成不同的執行計劃,然後選取一中最優的執行計劃,哪種執行計劃開銷小就選擇哪種。

優化器可以做哪些事情:

  1. 查詢重寫:将複雜的查詢語句轉換為等效但更簡單的形式,以減少計算和存儲成本。
  2. 查詢優化:考慮多種執行政策和連接配接方式,并估計每個選擇的成本,以選擇最優的執行計劃。
  3. 索引選擇
  4. 連接配接順序優化
  5. 子查詢優化

6.「執行器」

調用存儲引擎的api執行sql,執行查詢,并将結果傳回。其中查詢語句是查詢Buffer Pool,如果Buffer Pool沒有發出去缺頁提醒,去磁盤查找并将資料頁存儲到Buffer Pool,最後将結果傳回,以上就是查詢的流程。

Update語句的執行流程

更新用到了日志和緩存,先來補充日志和緩存。

binlog

binlog用于記錄資料庫執行的寫入操作不包括查詢,用二進制形式儲存在磁盤中。binlog是server層,也就是不管是什麼存儲引擎都會有。binlog是采用追加方式寫入的,順序寫。

binlog主要的使用場景有主從複制和資料恢複。binlog資料恢複也可以被稱為重放操作。因為在使用binlog檔案進行資料恢複時,會重放在該檔案中記錄的所有操作以實作資料的復原,進而達到恢複資料的目的。

redo log

mysql事務的四大特性之一持久性,隻要事務送出就被永久儲存下來,為了防止mysql拓機,Buffer Poll沒來的及刷入磁盤,導緻資料丢失,由于Innodb是以頁為機關進行互動,如果一個事務隻修改幾個位元組,那麼重新整理整個頁面太浪費性能。如果一個事務是跨好多頁修改,這些頁面不連續使用随機IO寫入性能太差。是以mysql設計了redo log,隻是記錄事務對資料也做了哪些修改,比如xx表空間中yy資料頁zz偏移量做了xx更新,記錄修改後的值,屬于實體日志。

mysql每執行一條DML語句都先寫入 redo log buffer,後續某個時間點在一次性将多個操作寫入到 redo log file。先寫日志再寫磁盤,這種就是經常說的WAL(write-ahead logging)技術。有了 redo log,InnoDB 就可以保證即使資料庫發生異常重新開機,之前送出的記錄都不會丢失,這個能力稱為crash-safe。

一條MySQL更新語句是如何執行的?

wal

mysql支援三種将redo log buffer分别是

  • 0(延時寫):每秒寫入OS Buffer并調用fsync寫入磁盤,當系統崩潰會丢失1秒鐘的資料
  • 1(實時寫):每次送出都會寫入OS Buffer并且調用fsync,這種不會丢失資料,性能差。
  • 2(實時寫,延時刷):每次送出都會從寫入os buffer,然後每秒調用fsync寫入日志。
一條MySQL更新語句是如何執行的?

寫入時機

redo log采用了大小固定,循環寫入的方式。write pos 是目前記錄的位置,一邊寫一邊後移,checkpoint 是目前要擦除的位置,也是往後推移并且循環的,擦除記錄前要把記錄更新到資料檔案。write pos 和 checkpoint 之間的是還空着的部分,可以用來記錄新的操作。如果 write pos 追上 checkpoint,這時候不能再執行新的更新,得停下來先擦掉一些記錄,把 checkpoint 推進一下。

一條MySQL更新語句是如何執行的?

循環寫入

「崩潰恢複和重新開機mysql,redo log都做了什麼?」

在資料庫重新啟動後,崩潰恢複機制會開始執行,以恢複資料庫的一緻性和持久性。崩潰恢複過程首先會檢查redo log中記錄的事務修改操作。

  • 在資料庫啟動時,會記錄目前的LSN值,表示崩潰之前已經寫入redo log的位置。
  • 在崩潰恢複過程中,從redo log中讀取日志記錄,并檢查其LSN值。

如果LSN小于目前LSN值,表示該日志記錄是在崩潰之前寫入redo log的操作,需要重新應用該日志記錄中的修改操作。

如果LSN大于或等于目前LSN值,表示該日志記錄是在崩潰之後寫入redo log的操作,可以忽略或跳過該日志記錄。

undo log

Undo log(復原日志)是資料庫管理系統中的一種機制,用于實作事務的復原操作和資料的一緻性維護。它記錄了事務執行期間對資料庫進行的修改操作,以便在需要復原事務或進行崩潰恢複時能夠撤銷這些修改,将資料恢複到事務開始之前的狀态。

1.「記錄修改操作」:

在事務執行期間,如果對資料庫中的資料進行了修改(例如插入、更新或删除操作),則将相應的修改操作記錄到Undo log中。

Undo log記錄了原始資料的邏輯操作,即如何撤銷事務對資料的修改。

2.「撤銷操作」:

當需要復原事務時,資料庫引擎會利用Undo log中的資訊,按照相反的順序執行記錄的修改操作,将資料恢複到事務開始之前的狀态。

3.「崩潰恢複」:

在資料庫崩潰後重新啟動時,可以使用Undo log來撤銷未送出事務的修改,以保持資料庫的一緻性。

通過使用Undo log,資料庫能夠實作事務的復原操作,保證資料的一緻性,并在崩潰恢複過程中恢複資料庫到崩潰前的狀态。它是實作事務的隔離性和持久性的重要組成部分。

buffer poll

用于緩存資料庫中的資料頁。它起到了提高資料庫性能的作用,通過将磁盤上的資料加載到記憶體中,減少磁盤通路的頻率。

當需要讀取資料時,資料庫首先在Buffer Pool中查找相應的資料頁,如果找到則直接傳回資料,避免了磁盤IO操作。當需要寫入資料時,資料庫将資料先寫入Buffer Pool中的資料頁,然後由背景線程定期将修改的資料頁重新整理到磁盤。

更新執行的流程

更新流程一樣也要走一遍查詢,因為更新之前必須拿到(查詢)更新的資料。

  1. 追加undo:順序将舊值寫入undo磁盤檔案。
  2. 更新buffer pool:将buffer pool中資料更新。
  3. 寫redo緩存:先将redo日志寫入redo buffer。
  4. 追加redo:從redo buffer中拿到資料 順序寫redo磁盤檔案。
  5. 追加binlog:順序寫binlog磁盤檔案。
  6. 打标記:寫入commit标記至redo磁盤檔案中,代表本次update的事務已經commit了,且redo與binlog一緻了。
  7. 刷盤:單獨有線程會将buffer pool中資料刷至磁盤,以随機的方式。

「為什麼要二階段送出?」

兩階段送出(簡稱2PC)是為了保證分布式系統中的多個參與者在進行事務送出時的資料一緻性而引入的協定。它確定了在事務送出過程中,所有參與者要麼都送出事務,要麼都復原事務,進而保持資料的一緻性。

  1. 準備階段(Prepare Phase):協調者向所有參與者發送事務準備請求,參與者執行事務操作,并将結果回報給協調者。如果所有參與者都準備好送出事務,協調者将發送送出請求;如果任何一個參與者未能準備好送出事務,協調者将發送復原請求。
  2. 送出階段(Commit Phase):協調者根據準備階段的回報結果,決定是發送送出請求還是復原請求。如果所有參與者都準備好送出事務,協調者發送送出請求,參與者将正式送出事務并釋放資源;如果任何一個參與者未能準備好送出事務,協調者發送復原請求,參與者将復原事務并釋放資源。

如果沒有使用兩階段送出協定,可能會導緻資料不一緻的問題,具體如下:

  1. 先寫Redo Log,再寫Binlog: 如果在寫完Redo Log後發生MySQL當機,而尚未寫入Binlog,那麼在重新開機後,Redo Log中存在事務記錄,MySQL會認為這些事務已成功送出,但是由于Binlog缺失了相應的記錄,導緻Binlog與Redo Log的資料不一緻。在以後使用Binlog進行資料恢複時,會出現資料丢失的情況。
  2. 先寫Binlog,再寫Redo Log: 如果在寫完Binlog後發生MySQL當機,而尚未寫入Redo Log,那麼在重新開機後,Redo Log中将沒有相應的記錄,MySQL會判斷這些事務未成功送出,但是由于Binlog中存在這些記錄,導緻Binlog與Redo Log的資料不一緻。在以後使用Binlog進行資料恢複時,會多出一個未送出的事務操作。

繼續閱讀