主頁 > 軟體設計 > MySQL架構分析

MySQL架構分析

2021-02-14 11:56:21 軟體設計

MySQL架構分析

MySQL 的體系結構

MySQL 的模塊詳解

image.png

  • **Connectors**:用于支持各種語言與 **SQL** 互動;
  • **Management Services & Utilities**:系統管理和控制工具(備份恢復、MySQL 復制、集群等);
  • **Connection Pool**:連接池,用戶管理需要緩沖的資源(用戶密碼、權限、執行緒等);
  • SQL Interface:用于接收用戶的 **SQL** 命令并回傳用戶需要的查詢結果;
  • **Parser**:用于決議 **SQL** 陳述句;
  • **Optimizer**:查詢優化器
  • **Caches & Buffers**:查詢緩沖,除了行記錄的快取,還有表、**Key**、權限快取等;
  • **Pluggable Storage Engines**:插件式存盤引擎,主要提供 **API** 給服務層使用,與具體的檔案互動,

MySQL 的架構分層

可以把 **MySQL** 分為與客戶端互動的連接層、執行操作的服務層和與硬體互動的存盤引擎層

image.png

  • 連接層:當客戶端需要連接到 **MySQL** 服務器的 **3306** 埠時,就需要與服務端建立連接;在連接層中就完成所有連接的管理、客戶端的身份和權限驗證;
  • 服務層:連接層會把 **SQL** 陳述句傳遞給服務層;在服務層中會做查詢緩沖的判斷、根據 **SQL** 呼叫相對應的介面以及對 **SQL** 陳述句進行語法和詞法的決議;最后在 **MySQL**** **的底層會根據一些規則對 **SQL** 陳述句進行優化后交給執行器去執行;
  • 存盤引擎層:在 **MySQL** 中資料存放的地方,**MySQL** 里支持不同的存盤引擎,

查詢 SQL 陳述句的執行流程

image.png

通信協議

**MySQL** 支持多種通信協議,可以使用同步和異步的方式,還支持長連接和短連接;當使用 **Linux** 服務器去登錄 **MySQL** 并沒有指定 **-h** 引數情況下,使用的是 **socket** 方式登錄,如果指定了 **-h** 引數情況下就是使用的 **TCP/IP** 協議,只能在 **Windows** 上使用的通信方式還有命名管道和記憶體共享的方式,

通信方式

image.png

  • 單工:在兩臺計算機通信時,資料的傳輸方向是單向的

  • 半雙工:在兩臺計算機之間的資料傳輸是雙向的;在這個通訊連接里,同一時間只能有一臺服務器在發送資料

  • 全雙工:在兩臺計算機之間的資料傳輸是雙向的;并且可以同時傳輸,

  • **MySQL** 中使用的是半雙工的通信方式,在客戶端給服務端發送資料時,服務端不能想客戶端發送資料,也就是說兩個動作不能同時發生,所以在客戶端發送 **SQL** 陳述句到服務端需要一次性發送,而不能分成小塊發送,在使用 **MyBatis** 動態 **SQL **生成一個批量插入的陳述句時,生成的陳述句太長會出現問題;這時就需要調整在 **MySQL** 中的引數配置 **max_allowed_packet** 值,因為他默認是 **4M**,如果不調整就會出錯,另外,對于服務端來說;不能在取得想要的資料時中斷 **MySQL** 的操作,因為會對網路和記憶體產生大量的消耗,所以在程式里避免不帶 **limit** 的操作,可以先 **count** 一下,如果有資料量就分批查詢,

同步和異步

  • 同步通信特點:
    • 同步通信依賴于被呼叫方,受限于呼叫方的性能;在應用操作資料庫時,執行緒會阻塞去等待資料庫的回傳
    • 一般只能做到一對一地通信,
  • 異步通信特點:
    • 異步可以避免應用阻塞等待,但不能節省 **SQL** 的執行時間;
    • 如果異步存在并發,每一個 **SQL** 的執行都需要單獨建立一個連接,避免資料混亂;但這樣會給服務端增加壓力(當創建新的連接的時候也會創建一個執行緒,執行緒之間切換會占用大量的 **CPU** 資源),除此之外,異步通信還帶來了編碼的復雜度,當要使用異步的時候就必須要使用連接池,排隊從連接池獲取連接而不是創建新的連接;一般情況下連接資料庫都是同步連接,

長連接和短連接

  • **MySQL** 同時支持長連接和短連接:
    • 短連接在操作完成后就關閉;
    • 長連接可以保持打開,這樣減少服務端創建和釋放連接的消耗,讓后續訪問時可以使用該連接,保持長連接會消耗記憶體,長時間不活動的連接,**MySQL** 服務器會斷開(默認 8 小時),
-- 非互動式超時時間
show global variables like 'wait_timeout'; 
-- 互動式超時時間
show global variables like 'interactive_timeout'; 

-- 查看 MySQL 當前有多少個連接 
-- Threads_cached:快取中的執行緒連接數
-- Threads_connected:當前打開的連接數
-- Threads_created:為處理連接創建的執行緒數
-- Threads_running:非睡眠狀態的連接數,通常指并發連接數
show global status like 'Threads_%';

-- 通過命令查看 MySQL 5.7 版本中默認的最大連接數是 151 個,最大可以設定成 16384(2^14)
-- show 命令默認是 session 級別,全域 global 級別;set 后重啟會失效,可以通過修改 mycnf 讓配置永久生效
show variables like 'max_connections';

查詢快取

  • **MySQL** 的內部自帶了一個快取模塊;快取主要是把資料以 **Key-Value** 的形式放到記憶體中,這樣可以加快資料的讀取速度,也可以減少服務器的處理時間, **MySQL** 的快取默認是關閉的,可以通過以下陳述句查看,
show variables like 'query_cache%';
  • **MySQL** 中把自帶的快取給關閉的原因主要是因為 **MySQL** 中的快取應用場景有限,在 **MySQL 8.0** 中的查詢快取已經被移除了,使用 **MySQL** 快取的要求:
    • **SQL** 陳述句必須完全一致;
    • 表里面的任務資料發生變化時,該表所有的快取都會失效,

語法/詞法決議

  • 當沒有使用快取時就會呼叫快取模塊并進入到 **Paser** 決議器; **Paser** 決議器主要是對陳述句基于 **SQL** 語法進行語法和詞法的決議:
    • 詞法決議就是把一個完整的 **SQL** 陳述句拆分成一個個的單詞;
    • 語法決議會對 **SQL** 做一些語法的檢查(單引號是否閉合,關鍵字是否錯誤等),然后根據 **MySQL** 定義的語法規則,然后根據 **SQL** 陳述句生成一個資料結構,

image.png

前處理器

  • 在前處理器中可以對語法進行分析;當寫了一個語法和詞法都正確的 **SQL** 陳述句時,但表或欄位不存在的情況下,還是會在決議的時候報錯,在決議 **SQL** 陳述句的環節中有前處理器;首先會檢查生成的決議樹,解決決議器無法決議的語意,預處理后會得到一個新的決議樹,

查詢優化

  • **MySQL** 中對一條 **SQL** 陳述句是有很多種執行方式,最終都是回傳一致的結果;而選擇執行方式的判斷標準是根據 **MySQL** 的查詢優化器模塊,它的作用就是根據決議樹生成不同的執行計劃,然后選擇一種最優的執行計劃;在 **MySQL** 里使用的是基于開銷的優化器,是選擇使用開銷最小的執行計劃,
-- 查看查詢的開銷
show status LIKE 'Last_query_cost';
  • 在默認情況下優化器的追蹤是關閉的,開啟該優化器的追蹤會消耗性能,因為它要把優化分析的結果寫到表中
-- 查看優化器的追蹤狀態
SHOW VARIABLES LIKE 'optimizer_trace'; 
-- 開啟優化器的追蹤
SET optimizer_trace='enabled=on';
-- 執行一條查詢陳述句,然后查詢優化器會生成執行計劃
SELECT fileds FROM `table` WHERE condition; 
-- 優化器分析的程序記錄到系統表中,查詢系統表中的優化器的追蹤資料,保存的是 JSON 資料
-- 分為準備階段、優化階段和執行階段
SELECT * FROM information_schema.optimizer_trace
-- 分析完后關閉
set optimizer_trace="enabled=off"; 
-- 再次查看是否關閉成功
SHOW VARIABLES LIKE 'optimizer_trace';
  • 當優化器優化完后會把決議樹變成一個查詢執行計劃,查詢執行計劃是一個資料結構,在 **MySQL** 中提供了一個執行計劃的工具,在 **SQL** 陳述句前加上 **EXPLAIN** 就可以查看到執行計劃的資訊,
EXPLAIN SELECT fileds FROM `table` WHERE condition; 

執行引擎

  • 執行引擎利用存盤引擎提供的相應的 **API** 去使用執行計劃操作存盤引擎,最后把資料回傳給客戶端,

存盤引擎

  • **MySQL** 中創建的每一張表都可以指定它的存盤引擎,存盤引擎的使用是以表為單位,
-- 查看指定表的存盤引擎
show table status from `tableName`;
-- 查看資料庫存放資料的路徑
show variables like 'datadir';
  • **MySQL** 的存放資料的路徑中可以看到每個存盤引擎都有一個 **.frm** 檔案,該檔案是表結構的定義檔案,不同的存盤引擎存盤資料的方式是不一致的:
    • **InnoDB** 引擎產生 **1** 個檔案;
    • **MyISAM** 引擎 產生 **2** 個檔案;
    • **Memory** 引擎不產生檔案;
  • **MySQL 5.5** 版本之前默認使用的是 **MyISAM** 存盤引擎,而在 **MySQL 5.5** 之后的默認存盤引擎就修改為了 **InnoDB**;主要原因是因為 InnoDB 支持事務和行級別的鎖,更適合對于業務一致性要求比較高的情況,
  • 可以使用 **SHOW ENGINES;** 命令查看資料庫對存盤引擎的支持情況;其中有存盤引擎的描述、對事務、**XA** 協議以及 **Savepoints** 的支持:
    • **XA** 協議用來實作分布式事務(本地資源管理器、事務管理器)
    • **SavePoints** 用來實作分布式子事務(嵌套事務),在創建 **SavePoints** 后,事務就可以回滾到這個保存點,不會影響到創建保存點之前的操作,
  • 存盤引擎的特性
FeatureMyISAMMemoryInnoDBArchiveNDB
B-tree indexesYesYesYesNoNo
Backup/point-in-time recovery (note 1)YesYesYesYesYes
Cluster database supportNoNoNoNoYes
Clustered indexesNoNoYesNoNo
Compressed dataYes (note 2)NoYesYesNo
Data cachesNoN/AYesNoYes
Encrypted dataYes (note 3)Yes (note 3)Yes (note 4)Yes (note 3)Yes (note 3)
Foreign key supportNoNoYesNoYes (note 5)
Full-text search indexesYesNoYes (note 6)NoNo
Geospatial data type supportYesNoYesYesYes
Geospatial indexing supportYesNoYes (note 7)NoNo
Hash indexesNoYesNo (note 8)NoYes
Index cachesYesN/AYesNoYes
Locking granularityTableTableRowRowRow
MVCCNoNoYesNoNo
Replication support (note 1)YesLimited (note 9)YesYesYes
Storage limits256TBRAM64TBNone384EB
T-tree indexesNoNoNoNoYes
TransactionsNoNoYesNoYes
Update statistics for data dictionaryYesYesYesYesYes

MyISAM

  • **MyISAM**** 存盤引擎中有 **3** 個檔案(.frm/.MYI/.MYD**)并且是 **MySQL 5.5** 之前的默認存盤引擎;其應用范圍比較小,表級鎖限制了讀和寫的性能;在 **Web** 和資料倉庫配置中,通常用于只讀或以讀為主的作業,適合只讀之類的資料分析的專案;
    • .MYD:是 **MyISAM** 存盤引擎中存放資料記錄的檔案;
    • .MYI:是 **MyISAM** 存盤引擎中存放索引的檔案;
      • **MyISAM** 存盤引擎的 **B+ Tree** 里,葉子節點存盤的是資料檔案對應的磁盤地址,所以從索引檔案 **.MYI** 中找到鍵值后就會到資料檔案 **.MYD** 中獲取相應的資料記錄,

image.png

  • **MyISAM** 存盤引擎中的輔助索引也在 **.MYI** 檔案里,輔助索引和主鍵索引存盤和檢索資料的方式是一致的,也在索引檔案中找到磁盤地址,然后到資料檔案中獲取資料,

image.png

  • 特點:
    • 支持表級別鎖(插入和更新會鎖表),不支持事務;
    • 有比較高的插入和查詢速度;
    • 存盤了表的行數(**count** 速度更快);
    • 適用于只讀之類的資料分析的專案

InnoDB

  • **InnoDB** 存盤引擎中有 **2**** **個檔案(**.frm/.ibd**)并且是 **MySQL 5.5** 之后的默認存盤引擎;它是一個事務安全的 **MySQL** 存盤引擎,具有提交、回滾和崩潰恢復功能來保護用戶的資料,**InnoDB** 中的行級鎖和 **Oracle** 的一致,對于非鎖讀提高了多用戶并發性和性能;**InnoDB** 將用戶資料存盤在聚集索引中,用于減少基于主鍵的常見查詢的 **I/O**,為了保證資料的完整性,**InnoDB** 還支持外鍵參考完整性的約束,
  • **InnoDB** 里是以主鍵為索引來組織資料的存盤,所以索引檔案和資料檔案是同一個檔案,都在 **.ibd** 檔案里面,在 **InnoDB** 的主鍵索引的葉子節點上直接存盤了資料,在 **InnoDB** 中的聚集索引(聚簇索引)是指索引鍵值的邏輯順序和表資料行的物理存盤順序是一致的;它組織資料的方式叫做聚集索引組織表,所以主鍵索引就是聚集索引,非主鍵都是非聚集索引,

image.png

  • **InnoDB** 存盤引擎中主鍵索引和輔助索引有主次關系;輔助索引存盤的是輔助索引和主鍵值,當使用輔助索引查詢時,就會根據主鍵值在主鍵索引中查詢,最終取得資料,比如在 **name** 欄位上創建一個索引,然后查詢 **name = 'John'**,它會在葉子節點找到主鍵值,也就是 **id = 1**,然后再到主鍵索引的葉子節點拿到資料,在輔助索引里存盤的是主鍵值而不是主鍵的磁盤地址的原因是 **B Tree** 有分叉與合并的操作,這時鍵值的地址會發生變化,所以在輔助索引里不存存盤地址,
  • 是否存在主鍵情況:
    • 當定義了主鍵時,**InnoDB** 會選擇主鍵作為聚集索引;
    • 當沒有顯示地定義主鍵時,**InnoDB** 就會選擇第一個不包含有 **NULL** 值的唯一索引作為主鍵索引;
    • 當沒有這樣的唯一索引時,**InnoDB** 會選擇內置 **6** 個位元組長的 **Rowid** 作為隱藏的聚集索引,它會隨著記錄的寫入而主鍵遞增,

image.png

  • 特點:
    • 由于支持事務、外鍵的原因讓資料的完整性和一致性更高;
    • 支持行級別和表級別鎖;
    • 支持讀寫并發,寫不阻塞讀(**MVCC**);
    • 特殊的索引存放方式,可以減少 **I/O**,提高查詢效率;
    • 適用于經常更新的表和存在并發讀寫或有事務處理的業務系統,

Memory

  • **Memory** 存盤引擎中只有一個檔案并將所有的資料存盤在 **RAM** 中;為了在需要快速查找非關鍵資料的環境中快速地訪問,該引擎也稱之為堆引擎,它的使用率正在減少,在 **InnoDB** 的緩沖池記憶體區域中提供了一種通用和持久的方式去將大部分或所有資料保存在記憶體中,而 **ndbcluster** 為大型分布式資料集提供了快速 **KV** 查找,其特點是:
    • 把資料放在記憶體里,讀寫速度都很快;但資料庫重啟或崩潰后,資料會全部消失,適用于做臨時表;
    • 將表中的資料存盤到記憶體中;

CSA

  • **CSV 存盤引擎中有 **3** **個檔案,它的表是帶逗號分隔值的文本檔案;**CSV** 表允許使用 **CSV** 格式匯入或轉儲資料,以便與讀寫相同格式的腳本和應用程式交換資料,因為在 **CSV** 表中沒有索引,所以通常在操作時將資料保存在 **InnoDB** 表中,并且只有在匯入匯出節點使用 **CSV** 表,它的特點是:
    • 不能空行,不支持索引;**CSV** 格式是通用的,可以直接編輯,適合在不同資料庫之間匯入匯出,

Archive

  • **Archive** 存盤引擎中只有 **2** 個檔案,這些緊湊并未索引的表用于存盤和檢索大量很少參考的歷史、存檔以及安全審計資訊,它的特點是:
    • 不支持索引,不支持 **update、delete** 操作
  • 存盤引擎的選擇:
    • 當對資料的一致性要求比較高且需要事務支持的業務系統可以選擇 **InnoDB** 存盤引擎;
    • 當資料查詢多更新少且對查詢性能要求比較高的業務系統可以選擇 **MyISAM** 存盤引擎;
    • 當需要一個用于查詢的臨時表的業務系統可以選擇 **Memory** 存盤引擎;
    • 當所有的存盤引擎不滿足業務系統的需求時可以自定義存盤引擎

更新 SQL 陳述句的執行流程

  • 在資料庫中的 **update** 操作包括了 **insert、delete、update**,更新和查詢的流程基本一致;也是需要經過決議器、優化器的處理,最后交給執行器;它們之間的區別是拿到符合條件的資料后的操作,

緩沖池

  • **InnoDB** 存盤引擎的資料都是放置在磁盤上的,**InnoDB** 操作資料有一個最小的邏輯單位(頁:索引頁和資料頁);由于磁盤的速度太慢,所以對資料不是每次都直接操作磁盤,在 **InnoDB** 存盤引擎中使用了一種緩沖池的技術,把磁盤讀取到的頁放到一塊記憶體區域中 **Buffer Pool**,下次讀取相同的頁會先判斷是否在緩沖池中,如果是就直接讀取,不用再次訪問磁盤,在修改資料時,先修改緩沖池中的頁;記憶體的資料頁和磁盤資料不一致時,就稱之為臟頁,在 **InnoDB** 中有指定的后臺執行緒把 **Buffer Pool** 的資料寫入到磁盤中,每隔一段時間就一次性地把多個修改寫入磁盤,這個動作稱之為刷臟,**Buffer Pool****InnoDB** 中非常重要的一個結構,其內部主要分為 **Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer**

InnoDB 記憶體結構和磁盤結構

u=4143057237,1402304381&fm=15&gp=0.jpg

記憶體結構

  • **Buffer Pool**:主要對頁面資訊(資料頁、索引頁)進行快取;可以查看 **Buffer Pool** 狀態資訊,其默認大小是 **128M**,當記憶體中的緩沖池寫滿了后,**InnoDB** 存盤引擎會采用 **LRU** 演算法來管理緩沖池,經過淘汰的資料就是熱點資料,記憶體緩沖區對于讀寫上提升了很大的性能,
-- 查看 Buffer Pool 資訊
SHOW STATUS LIKE '%innodb_buffer_pool%';
  • **Change Buffer**:在 **MySQL 5.5** 之前稱之為 **Insert Buffer** 插入緩沖,現在叫做 **Change Buffer**,當這個資料頁不是唯一的索引時,不存在資料重復的情況,也就不需要從磁盤中加載索引頁判斷資料是否重復(檢查唯一性),在這種情況下為了提升更新陳述句的執行速度,可以先把修改記錄在記憶體的緩沖池中,在最后把 **Change Buffer** 記錄到資料頁的操作稱之為 **merge**; 當訪問這個資料頁、或者通過后臺執行緒、或資料庫 **shut down、redo log** 寫滿時就觸發,當資料庫中的大部分索引都是非唯一索引且業務是寫多讀少的情況下,不會在寫資料后立刻讀取時,就可以使用 **Change Buffer**
-- 查看 Change Buffer 占用 Buffer Pool 的比例:默認 25%
SHOW VARIABLES LIKE 'innodb_change_buffer_max_size';
  • **Adaptive Hash Index**

  • **Log Buffer**:當 **Buffer Pool** 中的臟頁還沒刷入到磁盤時,資料庫就宕機或重啟,這些資料就為被丟失,當寫操作寫到一半時,甚至可能會破壞資料檔案,從而導致資料庫不可用,為了規避該問題,**InnoDB** 存盤引擎中對所有頁面的修改操作寫入到一個日志檔案中,并且在資料庫啟動時從這個檔案進行恢復操作;主要使用它來實作事務的持久性,該檔案就是磁盤的 **redo log**,對應于 **ib_logfile0、ib_logfile1** 檔案,每個檔案的大小是 **48M**,這個主要是先把操作寫入日志,然后再寫磁盤,

image.png

-- innodb_log_file_size:指定每個檔案的大小,默認 48M
-- innodb_log_files_in_group:指定檔案的數量,默認為 2
-- innodb_log_group_home_dir:指定檔案所在路徑,相對或絕對;不指定時為 datadir 路徑
show variables like 'innodb_log%';

image.png

  • 在同樣是寫磁盤,先寫日志在寫磁盤和不直接寫到 **DB file** 的原因是因為刷盤是隨機 **I/O**,而記錄日志是順序 **I/O**,順序 **I/O** 的效率比隨機 **I/O** 高,所以先把修改寫入日志就可以實作延遲刷盤的時機來提升系統的吞吐,先看一下隨機 **I/O** 和順序 **I/O**
    • 隨機 **I/O**:磁盤最小的組成單元是扇區,通常是 **512 byte**;作業系統和記憶體互動的最小單位是 **page**;作業系統和磁盤互動的最小單位是 **block**,當所需要的資料是隨機分散在不同頁的不同扇區時,就要找到相應的資料需要等到磁臂旋轉到指定的也,然后盤片尋找對應的扇區才能找到我們所需要的一塊資料;一次進行此程序直到找完所有的資料,它的讀取速度比較慢,
    • 順序 **I/O**:當已經找到了第一塊資料且其他所需要的資料就在這塊資料的后面時,不要重新尋址就可以依次拿到我們所需要的資料,
  • **redo log** 也不是每次都直接寫入到磁盤中,在 **Buffer log** 中有一塊記憶體區域 **Log Buffer** 用來保存即將要寫入日志檔案的資料,默認大小是 **16M**,它可以節省磁盤 I/O ,可以通過下面命令查看大小:

image.png

-- 查看 Log Buffer 大小
SHOW VARIABLES LIKE 'innodb_log_buffer_size';
  • 其實 **redo log** 中的內容主要是用于崩潰恢復,磁盤的資料檔案中的資料來自 **Buffer Pool****redo log** 是寫入磁盤而不是寫入資料檔案,當寫入資料到磁盤時,作業系統本身是有快取的,**flush** 操作就是把作業系統的緩沖區寫入到磁盤,而 **Log Buffer** 寫入磁盤時由一次引數進行控制的:默認為 **1**
-- 0 表示延遲寫:log buffer 每秒一次地寫入 log file 中且 log file 的 flush 操作同時進行;
-- 當事務提交時,不會主動觸發寫入磁盤的操作;

-- 1 表示默認,實時寫和刷:每次事務提交時, MySQL 都會把 log buffer 的資料寫入 log file且刷到磁盤中

-- 2 表示實時寫,延遲刷:每次事務提交時 MySQL 都會把 log buffer 的資料寫入 log file;
-- 但 flush 操作并不會同時進行,MySQL 會每秒執行一次 flush 操作
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';

image.png

image.png

  • **redo log** 又分為記憶體和磁盤兩部分,其特點是:
    • **redo log****InnoDB** 存盤引擎實作的,并不是所有存盤引擎都擁有;
    • 不是記錄資料頁更新后的狀態,而是記錄該頁做了什么操作,屬于物理日志;
    • **redo log** 的大小是固定的,前面的內容會被覆寫,
  • **check point** 表示當前要覆寫的位置,當 **write pos****check point** 重疊時,說明 **redo log** 已滿,這時就需要同步 **redo log** 到磁盤中,

磁盤結構

[表空間](https://dev.mysql.com/doc/refman/5.7/en/innodb-on-disk-structures.html)可以看成 `**InnoDB**` 存盤引擎邏輯結構的最高層,所有的資料都存放在表空間中,

System TableSpace

  • 在默認情況下 **InnoDB** 存盤引擎有一個共享表空間(系統表空間),在系統表空間中主要包含 **InnoDB** 資料字典、雙寫緩沖區、**Change Buffer****Undo Log**;當沒指定 **file-per-table** 時也包含了用戶創建的表和索引資料,**InnoDB** 和作業系統的頁大小不一致,**InnoDB** 頁大小一般為 **16KB**,而作業系統頁大小為 **4K**;所以 **InnoDB** 的頁需要分成 **4** 次寫入到磁盤,
    • **undo log** 是獨立的表空間;
    • 資料字典:由內部系統表組成,存盤表和索引的元資料定義資訊;
    • 雙寫緩沖區:**InnoDB** 存盤引擎的特性,

image.png

  • 當存盤引擎正在寫入頁的資料到磁盤時發生了宕機,可能出現頁只寫了一部分的情況;這種情況稱之為部分寫失效 **partial page write**,可能會導致資料丟失,雖然有 **redo log**,但這個頁本身已經損壞的情況下,使用它來做崩潰恢復是毫無意義的;所以在對于應用 **redo log** 前需要一個頁的副本,如果出現了寫入失效情況下,就使用頁的副本來還原這個頁,然后再應用 **redo log**,這個頁的副本其實就是 **InnoDB** 中的雙寫技術 **double write**,通過該方式實作了資料頁的可靠性,**double write****redo log** 類似,都是由兩部分組成:一部分是記憶體的 **double write**、一部分是磁盤的 **double write**,因為 **double write** 是順序寫入的,所以不會帶來很大的性能上開銷,在默認的情況下,所有的表共享一個系統表空間,這個檔案會越來越大,而且它的空間不會收縮,
show variables like 'innodb_doublewrite';

File-per-table TableSpace

  • 可以讓每張表獨占一個表空間;但是在這個開啟之后會對每張表開辟一個表空間,產生的檔案就是資料目錄下的 **.ibd** 檔案,該檔案主要是存放表的索引和資料的,但是其他型別的資料(回滾資訊、插入緩沖索引頁、 系統事務資訊、二次寫緩沖等)還是存放在原來的共享表空間內,
-- 查看表空間
SHOW VARIABLES LIKE 'innodb_file_per_table';

General TableSpace

  • 通用表空間也屬于共享表空間,用于存盤不同資料庫的表、資料路徑以及自定義檔案
-- 創建一個通用的表空間
create tablespace ts2673 add datafile '/var/lib/mysql/ts2673.ibd' file_block_size=16K engine=innodb;
-- 在創建時可以指定表空間,使用 ALTER 修改表空間可以轉移表空間,不同表空間的資料是可以移動的
create table t2673(id integer) tablespace ts2673;
-- 洗掉表空間是需要先洗掉里面所有的表
drop table t2673; 
drop tablespace ts2673;

Temporary TableSpace

  • 存盤臨時表的資料(用戶創建的臨時表、磁盤內部的臨時表);對應資料目錄下的 **ibtmp1** 檔案,當資料服務器正常關閉時,該表空間被洗掉,下次重新產生

Undo log TableSpace

  • 記錄了事務發生之前的資料狀態;當修改資料時出現了例外,就可以使用 **undo log** 來實作回滾操作(保持原子性),在執行 **undo** 時,只是把資料從邏輯上恢復到事務發生前的狀態,而不是從物理頁面上操作實作的,屬于邏輯格式的日志,**redo log****undo log** 統稱為事務日志;**undo log** 的資料默認存放在系統表空間 **ibdata1** 檔案中,因為共享表空間不會自動收縮,也可以單獨地創建一個 **undo** 表空間,
-- 查看 undo 表空間
show global variables like '%undo%';

后臺執行緒

  • 后臺執行緒的主要作用是負責重繪記憶體池中的資料和把修改的資料頁重繪到磁盤,后臺執行緒的分類:
    • **master thread**:負責重繪快取資料到磁盤并協調調度其他的后臺行程;
    • **IO thread**:分為 **insert buffer、log、read、write** 行程,分別用來處理 **insert buffer**、重做日志、讀寫請求的 **I/O** 回呼;
    • **purge thread**:用于回收 **undo**
    • **page cleaner thread**: 用于重繪臟頁

Binlog

  • **[Binary Log](https://dev.mysql.com/doc/refman/5.7/en/binary-log.html)** 是以事件的形式記錄了所有的 **DDL、DML** 陳述句操作而不是數值,所以 **Binary Log** 屬于邏輯日志;Binary Log**redo log** 不同,它的檔案內容是可以追加的且沒有大小限制,一般可以使用 **Binlog**** **實作的功能有:

    • 資料恢復:在開啟 **Binary Log** 功能的情況下,可以把它匯出成 **SQL** 陳述句并重新執行一遍;
    • 主從復制:從服務器讀取主服務器的 **binlog** 后再執行一遍,
  • 更新操作的流程: **SQL 陳述句:UPDATE person SET name = John where pid = 1;**,原 **name = Sky**

    • 首先事務開始,從記憶體或磁盤讀取這條陳述句的資料,如果有快取也會使用到快取,然后回傳給 **Server** 的執行器;
    • 執行器修改這行資料的值為 **John**** **后再呼叫引擎的 **API** 介面寫入這條資料到記憶體中;
    • 記錄 **name = Sky****undo log** 中和 **name = John****redo log** 中;這時 **redo log** 就進入到 **prepare** 狀態,然后通知執行器,執行完成可以提交事務;
    • 執行器收到通知后記錄 **binlog**,然后呼叫存盤引擎的 **API** 設定 **redo log****commit** 狀態;
    • 最后提交事務,更新完成,

image.png

image.png

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/259448.html

標籤:其他

上一篇:Jmeter性能測驗入門&主要指標

下一篇:咖啡汪日志——遇見數倉,理想與現實的碰撞,前景與難點的對接

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more