本文是在儲存引擎是innodb的前提下mysql中的針對表的操作可以分為增刪改查四種操作,也就是常說的crud**,根據型別分為dml(增刪改)和dql(查);今天就說下插入和查詢的語句時如何在mysql中執行的。
不管是dml還是dql都是要經過聯結器,快取,分析器,優化器,執行器呼叫儲存引擎的api。在前四個階段都是一樣的流程,具體的可以參考mysql基礎架構篇
扇區:磁碟儲存的最小單位,扇區一般大小為512byte。
磁碟塊:檔案系統與磁碟互動的的最小單位(計算機系統讀寫磁碟的最小單位),乙個磁碟塊由連續幾個(2^n)扇區組成,塊一般大小一般為4kb。
mysql的頁:mysql中和磁碟互動的最小單位稱為頁,預設大小是16kb,也就是4個磁碟塊。也就是說mysql在進行資料讀取的是預設情況下一次就是讀取16kb(可以修改),即是我只查詢一條大小只有1kb的資料,mysql讀取的也是16kb。
select查詢比較簡單,其實就是到硬碟上按照頁(16kb)把資料載入到記憶體,然後再去匹配where條件,找出符合條件的資料;
如果where條件沒有索引,那麼就是全表掃瞄,遍歷所有的資料頁到記憶體,然後乙個個匹配。
如果where條件是主鍵索引,那麼就會把主鍵索引的資料頁載入到記憶體,然後匹配到具體的行資料返回;
如果where條件是普通索引,那麼就會把普通索引的資料頁載入到記憶體,然後匹配到符合條件的葉子結點(b+樹的葉子結點),如果能夠使用覆蓋索引,那麼就會直接返回,如果不能使用覆蓋索引,則會進行回表查詢(走一次主鍵索引查詢)。覆蓋索引和回表不清楚的可以參考歷史文章:需要知道的索引基礎知識
更新語句首先要按照查詢的流程執行,因為肯定要先知道是哪條記錄,之後才能去更新這條記錄。之後就是更新了,更新操作涉及到幾個日誌的記錄,分別是undolog(innodb的回滾日誌) ,redolog(innodb的資料持久化日誌),binlog(mysql server的歸檔日誌),下面我們看下他們之間是怎麼配合完成資料更新的。
首先執行引擎按照條件找資料,如果記憶體中存在則直接返回,不存在查詢後返回。
執行器呼叫儲存引擎介面寫入資料,在快取池中修改這條記錄,。
寫redo日誌,先把資料更新到redo日誌的快取中。
準備提交事務,把redo日誌快取刷入磁碟。這時候redolog 是prepare階段(共有兩個階段prepare和commit),然後通知執行器完成。
執行器開始執行binlog寫入磁碟。
然後呼叫儲存引擎的事務提交介面,把redolog中的prepare改成commit狀態,至此更新完成。
之後有io執行緒以頁為單位隨機寫入磁碟,把我們更新後的資料慢慢落入磁碟中。
兩個日誌是分開寫的,所以很難保證兩個日誌資料一致,在恢復的時候盡量保證同時參考兩個日誌檔案,如果一致才會提交,不一致丟棄。
假如在步驟8的時候更新失敗,兩種情況
我們要更新的資料是存在磁碟的任意位置,是屬於隨機io,效率是很低的,這樣mysql的併發無法保證,而redo日誌和binlog屬於預寫日誌,都是順序io,直接寫入即可,效率要高很多,即是失敗了也可以根據日誌恢復。
網上看的的一張圖,畫的非常好為什麼要設計兩階段提交:
寫入的新資料屬於髒頁,只有更新到磁碟才能是完整的資料反證一下:
假如先寫redo log 後寫binlog:如果在redolog寫完,binlog還沒寫完,mysql崩潰重啟。重啟之後可以通過redolog恢復資料,但是binlog是沒有這條資料的,所以後續用binlog備份資料或者進行主從同步的時候都會丟失這條資料,這樣和原庫的資料是不一致的。
假如先寫binlog後寫redolog:在binlog寫完之後mysql崩潰,由於redolog 沒有寫入,奔潰重啟之後也不會也不會恢復資料,但是binlog中已經完整記錄這條記錄,所以之後binlog備份和主從同步會有這條資料,這樣和原庫又不一致了。
總結不管是查詢語句還是更新語句,都要先經過聯結器,查詢快取(8.0已經去掉了),分析器,優化器,執行器。
查詢語句要選按照查詢條件把資料所在的整頁載入到記憶體。
更新語句在查詢的基礎上利用undo log,redo log,bin log 完成資料的更新。
undo log是用來sql執行失敗之後回滾資料,保持事務的原子性。
redo log是用於mysql崩潰恢復,保證已提交事務的acid特性。
binlog是資料記錄的日誌檔案,用於資料備份,主從同步。
直接更新記錄然後刷盤是隨機io,效率低下,所以使用redolog順序寫,提高效率。
兩階段提交能夠崩潰恢復,保證資料的一致性。
個人**:紀先生高階指南
1. mysql高階系列:一文了
解mysql基礎架構;
2. mysql高階系列:一文了解mysql儲存引擎;
3. mysql高階系列:mysql中myisam和innodb有什麼區別;
4. mysql高階系列:mysql中表設計如何更好的選擇資料型別;
5. mysql高階系列:資料庫設計中的正規化究竟該如何使用;
6. mysql高階系列:一文詳解explain各欄位含義;
7. mysql高階系列:為什麼mysql使用b+作為索引的資料結構;
8. mysql高階系列: 你需要知道的一些索引基礎知識;
9. mysql高階系列:怎麼建立索引更合適;
10. mysql高階系列:主從複製原理和配置;
11. mysql高階系列:join連線的原理-3種演算法;
12. mysql高階系列:事務及事務隔離級別;
13. mysql高階系列:多版本併發控制-mvcc;
mysql 基礎架構以及一條 sql 是如何執行的
前言 作為乙個開發,避免不了和資料庫打交道,尤其是 mysql。往往只會用,但是沒有去 其 一條 sql 語句具體是怎麼樣去實現的,以及 mysql 的基礎架構,接下來將記錄在學習mysql 中的一些要點。mysql 基礎架構 mysql 主要分為 server 層 和 儲存引擎層。server 層...
MySQL之一條sql語句是如何執行的
大體來說,mysql可以分為server層和儲存引擎層兩部分 server層包括聯結器 查詢快取 分析器 優化器和執行器等,涵蓋mysql的大多數核心服務功能,以及所有的內建函式 如日期 時間 數學和加密函式等 所有跨儲存引擎的功能都在這一層實現,比如儲存過程 觸發器和檢視等。儲存引擎層負責資料的儲...
mysql 插入更新一條sql 搞定
插入資料時,我們經常會遇到這樣的情況 1 首先判斷資料是否存在 2 如果不存在,則插入 3 如果存在,則更新。在sql server中可以這樣處理 if not exists select 1 from t where id 1 insert into t id,update time values...