MySQL架構分析
MySQL 的體系結構
MySQL 的模塊詳解

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

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

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

-
單工:在兩臺計算機通信時,資料的傳輸方向是單向的;
-
半雙工:在兩臺計算機之間的資料傳輸是雙向的;在這個通訊連接里,同一時間只能有一臺服務器在發送資料
-
全雙工:在兩臺計算機之間的資料傳輸是雙向的;并且可以同時傳輸,
-
在
**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**陳述句生成一個資料結構,
- 詞法決議就是把一個完整的

前處理器
- 在前處理器中可以對語法進行分析;當寫了一個語法和詞法都正確的
**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**后,事務就可以回滾到這個保存點,不會影響到創建保存點之前的操作,
- 存盤引擎的特性
| Feature | MyISAM | Memory | InnoDB | Archive | NDB |
|---|---|---|---|---|---|
| B-tree indexes | Yes | Yes | Yes | No | No |
| Backup/point-in-time recovery (note 1) | Yes | Yes | Yes | Yes | Yes |
| Cluster database support | No | No | No | No | Yes |
| Clustered indexes | No | No | Yes | No | No |
| Compressed data | Yes (note 2) | No | Yes | Yes | No |
| Data caches | No | N/A | Yes | No | Yes |
| Encrypted data | Yes (note 3) | Yes (note 3) | Yes (note 4) | Yes (note 3) | Yes (note 3) |
| Foreign key support | No | No | Yes | No | Yes (note 5) |
| Full-text search indexes | Yes | No | Yes (note 6) | No | No |
| Geospatial data type support | Yes | No | Yes | Yes | Yes |
| Geospatial indexing support | Yes | No | Yes (note 7) | No | No |
| Hash indexes | No | Yes | No (note 8) | No | Yes |
| Index caches | Yes | N/A | Yes | No | Yes |
| Locking granularity | Table | Table | Row | Row | Row |
| MVCC | No | No | Yes | No | No |
| Replication support (note 1) | Yes | Limited (note 9) | Yes | Yes | Yes |
| Storage limits | 256TB | RAM | 64TB | None | 384EB |
| T-tree indexes | No | No | No | No | Yes |
| Transactions | No | No | Yes | No | Yes |
| Update statistics for data dictionary | Yes | Yes | Yes | Yes | Yes |
MyISAM
**MyISAM**** 存盤引擎中有**3**個檔案(.frm/.MYI/.MYD**)并且是**MySQL 5.5**之前的默認存盤引擎;其應用范圍比較小,表級鎖限制了讀和寫的性能;在**Web**和資料倉庫配置中,通常用于只讀或以讀為主的作業,適合只讀之類的資料分析的專案;.MYD:是**MyISAM**存盤引擎中存放資料記錄的檔案;.MYI:是**MyISAM**存盤引擎中存放索引的檔案;- 在
**MyISAM**存盤引擎的**B+ Tree**里,葉子節點存盤的是資料檔案對應的磁盤地址,所以從索引檔案**.MYI**中找到鍵值后就會到資料檔案**.MYD**中獲取相應的資料記錄,
- 在

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

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

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

- 特點:
- 由于支持事務、外鍵的原因讓資料的完整性和一致性更高;
- 支持行級別和表級別鎖;
- 支持讀寫并發,寫不阻塞讀(
**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 記憶體結構和磁盤結構

記憶體結構
**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**,這個主要是先把操作寫入日志,然后再寫磁盤,

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

- 在同樣是寫磁盤,先寫日志在寫磁盤和不直接寫到
**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,可以通過下面命令查看大小:

-- 查看 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';


**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**存盤引擎的特性,

- 當存盤引擎正在寫入頁的資料到磁盤時發生了宕機,可能出現頁只寫了一部分的情況;這種情況稱之為部分寫失效
**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**狀態; - 最后提交事務,更新完成,
- 首先事務開始,從記憶體或磁盤讀取這條陳述句的資料,如果有快取也會使用到快取,然后回傳給

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

