MySQL 基礎知識梳理學習(五)----詳解MySQL兩次寫的設計及實現

来源:https://www.cnblogs.com/xuliuzai/archive/2019/01/19/10290196.html
-Advertisement-
Play Games

一 . 兩次寫提出的背景或要解決的問題 兩次寫(InnoDB Double Write)是Innodb中很獨特的一個功能點。因為Innodb中的日誌是邏輯的,所謂邏輯就是比如插入一條記錄時,它可能會在某一個頁面(這條記錄最終被插入的位置)的多個偏移位置寫入某個長度的值,例如頁頭的記錄數、槽數、頁尾槽 ...


 一 . 兩次寫提出的背景或要解決的問題

兩次寫(InnoDB Double Write)是Innodb中很獨特的一個功能點。因為Innodb中的日誌是邏輯的,所謂邏輯就是比如插入一條記錄時,它可能會在某一個頁面(這條記錄最終被插入的位置)的多個偏移位置寫入某個長度的值,例如頁頭的記錄數、槽數、頁尾槽數據、頁中的記錄值等。這些本是一些物理操作,而Innodb為了節省日誌量及其它原因,設計為邏輯處理的方式,即在一個頁面上插入一條記錄時,對應的日誌內容包括表空間號、頁面號、將被記錄的各個列的值等內容,在真正物理插入的時候,才會將日誌邏輯操作轉換為前面的物理操作。

先有邏輯日誌,再有物理操作,但是這樣需要有一個前提,就是物理操作的頁面是正確的。如果那個數據頁面本身是錯誤的,這種錯誤可能是上次的操作導致的寫斷裂(1個頁面為16KB,分多次寫入,後面的可能沒有寫成功,導致這個頁面不完整)或者其它原因,那麼這個邏輯操作就沒辦法完成了。因為如果這個頁面不正確的話,裡面的數據是無效的,就可能會產生各種不可預料的問題。

因此首先要保證這個頁面是正確的,方法就是兩次寫。

二 . 單一頁面刷盤

兩次寫包括兩種方法,一種是對單獨一個頁面刷盤時的兩次寫,另一種是批量刷盤時的兩次寫。單一頁面刷盤實際上是MySQL5.5版本的實現方式。

2.1  結構設計及原理

MySQL在系統頁面上記錄關於兩次寫的信息如要如下:

參數變數 信息描述 說明
TRX_SYS_DOUBLEWRITE_FSEG 兩次寫頁面所在段的地址信息。 存儲兩次寫頁面所在段的地址信息,每次使用兩次寫機制寫數據時,都會從這個位置讀取到段的位置,找到段的首地址。
TRX_SYS_DOUBLEWRITE_MAGIC 用來判斷是不是已經初始化過兩次寫頁面。 存儲的是用來驗證當前兩次寫是不是正常或是不是已經申請的標誌。
TRX_SYS_DOUBLEWRITE_BLOCK1 兩次寫頁面第一個簇的首地址,兩次寫頁面總共兩個簇,一個簇為64個頁面。

存儲的是兩次寫空間的位置,他們在ibdata文件中屬於同一個段,在初始化資料庫時會確定具體問題,是用來真正存儲兩次寫頁面數據的空間,它們對應的空間大小都是一個簇,占用磁碟空間分別為1M。(一個簇為64*16KB=1M;2個簇,就是2M)

TRX_SYS_DOUBLEWRITE_BLOCK2 第二個簇的首地址。
TRX_SYS_DOUBLEWRITE_REPEAT 將上面的MAGIC、BLOCK1、BLOCK2重覆存儲,防止頁面自己的不完整。  

 

2.2 刷盤的過程

每次刷盤前,都會將要刷盤的頁面信息臨時保存到記憶體的數組中,這個空間大小也是128個頁面,這個緩存稱為兩次寫緩存數組。有了這些信息,單個頁面刷盤的兩次寫就可以正常運轉了。

step 1 先在兩次寫緩存數組中,找到一個空閑位置,並將這個位置標記為已使用,然後,再把要刷新的頁面數據複製到標記的緩存空間中。

step 2 將頁面的數據刷到兩次寫文件中,即ibdata文件中。此時頁面是持久化。

複製的數據量是一個頁面的大小,偏移位置是這個頁面在兩次寫緩存空間中的位置,對應著TRX_SYS_DOUBLEWRITE_BLOCK1或TRX_SYS_DOUBLEWRITE_BLOCK2的位置。因為記憶體中的兩次寫緩存數組是128個元素,而對應的TRX_SYS_DOUBLEWRITE_BLOCK1及TRX_SYS_DOUBLEWRITE_BLOCK2也是128個頁面,它們是一一對應的,所以具體刷到什麼位置,可以計算出來。

step 3 頁面刷盤,即數據刷到真實的位置,也許刷到的是ibdata文件,也許是某一個表的ibd文件中的某一個位置。

需要註意的是,因為Buffer Pool中的頁面,刷到真實文件時是非同步IO的,那麼只有當刷到自己表空間的刷盤操作完成後,兩次寫緩存數組的數據才可以被覆蓋,或者說,這個頁面對應的兩次寫文件中的頁面才可以被覆蓋,不然又可能造成這個兩次寫位置的頁面被新的頁面覆蓋的問題。如果此時上次的真實表空間的刷盤沒有完成,同時產生了頁面斷裂的問題,這樣就出現了該頁面不可恢復的問題,兩次寫的意義也就沒有了。

三 . 批量頁面刷盤

很明顯,單一刷盤情況下開啟了兩次寫,IO次數的增加會導致性能差很多,在新版本MySQL 5.7中,新增加入了針對Buffer Pool  批量刷盤的兩次寫實現方式。

3.1 實現原理 

MySQL 5.7的實現方式新增了一個文件,文件路徑及名稱可以通過參數innodb_parallel_doublewrite_path來控制。啟動資料庫時,如果兩次寫文件不存在,那麼這個參數可以指定絕對路徑的兩次寫文件,也可以只指定文件名使文件被預設創建到datadir目錄下。

批量刷盤包括兩種方式,分別是LRU方式和LIST方式。當Buffer Pool空間不足時,再載入新的頁面就必須要將一些不怎麼用到的、舊的頁面淘汰出去,此時系統就會從LRU鏈表中找到最老的頁面,進行批量刷盤,將釋放的空間加入到空閑空間中去,這種情況就是LRU刷盤。當日誌空間不足,或者是後臺MASTER線程在定時刷盤時,不需要區分頁面的新舊狀態,只需要選擇LSN最小的那些頁面,從前到後刷一批頁面到文件中,此時所用的策略就是LIST方式。

在批量刷盤的兩次寫中,這兩種刷盤方法對應的兩次寫空間互不幹涉。

InnoDB自身的整個Buffer Pool分為多個Instance,每個Instance管理自身的一套兩次寫空間,而針對每一個Instance的每一個刷盤方法的批量緩存空間大小,是通過參數innodb_doublewrite_batch_size來控制的,預設值為120。這樣算下來,innodb_parallel_doublewrite_path所指的文件大小的計算方法如下:

兩次寫文件頁面個數=innodb_buffer_pool_instances*2(LIST+LRU)*innodb_doublewrite_batch_size.

從圖中可以看出落到最終的每一個shard,其實就是一個batch,對應的參數就是innodb_doublewrite_batch_size。一個shard,有一個數組,長度為innodb_doublewrite_batch_size,與單一頁面刷盤的兩次寫是一樣的,只是這個數組只屬於一個shard而已。

3.2 批量刷盤的過程 

 假設由於頁面淘汰,系統要做一次批量刷盤,這次就是LRU方式的,那麼此時系統就需要將當前頁面加入到兩次寫緩存中,首先根據當前頁面所在的Instance號及刷盤類型就可以找到對應的shard緩存,找到緩存後,判斷當前shard是否已經滿了,即是否已經達到innodb_doublewrite_batch_size的大小,如果沒有達到,則將當前頁面內容追加複製到當前的shard緩存中,這樣當前頁面的刷盤操作就完成了。這裡並不像單一頁面那樣,先寫入緩存空間中,然後寫入ibdata文件的兩次寫空間,最後還需要立即將頁面的真實內容刷入表空間,對於批量刷盤來說,只需要寫入到shard緩存即可。

如果當前shard中緩存的頁面個數已經達到了innodb_doublewrite_batch_size,則說明當前緩存空間已經滿了,此時不得不將當前shard緩存的頁面寫入兩次寫文件中,寫完之後再將兩次寫文件FLUSH到磁碟,最後將對應的真實頁面刷盤,此時可能是隨機寫入了,因為對應的兩次寫緩存中雖然是連續的,但對應的真實頁面就不會這樣了。這裡需要註意的一點就是,表空間頁面的刷盤,是非同步IO操作,此時需要等待非同步IO完成,且整個shard中的頁面都刷盤後,刷盤操作才可以繼續向後執行,而這個shard也可以再次重新使用了,緩存中的數據也都會被清空。

需要註意的是,上面過程中寫入是連續innodb_doublewrite_batch_size 個頁面,所以性能會比寫入多次而每次致謝一個頁面的情況好很多。批量刷盤的情況下,有可能每隔innodb_doublewrite_batch_size個頁面的刷盤操作,就會出現一次等待操作,且等待時間長短不一定,但這也是在單一頁面刷盤的基礎上優化過的,做了改進。

四 . 兩次寫的作用

在資料庫啟動時(異常關閉的情況下),都會做資料庫恢復(redo)操作。在恢復的過程中,資料庫會檢查頁面是否合法(校驗),如果發現一個頁面的校驗結果不一致,則此時就會用到兩次寫機制,用兩次寫空間中的數據來恢復異常頁面的數據,這也正是為處理這樣的錯誤而設計的。此時的處理機制就是,將兩次寫的兩個簇都讀出來,再將innodb_parallel_doublewrite_path文件的內容讀出來,然後將所有這些頁面寫回到對應的頁面中去,這樣就可以保證這些頁面是正確的,並且是在寫入前已經更新過的(最新數據)。在寫回對應頁面中去之後,就可以在此基礎上繼續做資料庫恢復了,且不會遇到這樣的問題了,因為最後有可能產生寫斷裂的數據頁面都恢復了。

上面所講的都是數據頁面有問題的情況下可以通過兩次寫頁面來恢復,但是如果兩次寫頁面本身發生寫斷裂怎麼辦呢? 對於這個問題,大家不必擔心。因為如果兩次寫有問題,則數據頁面本身就不會做寫操作(一定是先邏輯後物理嘛,邏輯掛了,就沒有後面的物理了。),此時系統掛了,發生錯誤的是兩次寫頁面,而數據頁面在掛之前都是在Buffer裡面,文件中依然是當前事務操作前的值,並沒有變化,還是一致狀態,這意味著兩次寫頁面根本就不會用到。

 

 

-----主要內容參考梳理於網路知識,此短文僅為學習筆記,在此原創作者感謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、Samba服務 samba服務的安裝及配置: sudo apt-get install samba 二、配置: 1、創建一個需要共用的目錄,並修改許可權: lpf@ubuntu:~$ mkdir linux (此為需要設置共用的目錄,在這裡實現window 和) lpf@ubuntu:~$ sud ...
  • 1、使用VMWARE軟體安裝虛擬機,創建打開將進入桌面。 2、配置靜態IP。IP環境關係到能否使用網路進行軟體的下載,即apt的使用。 1)、找到文件並作如下修改:sudo vim /etc/network/interfaces 修改如下部分: auto eth0 iface eth0 inet s ...
  • 內核版本: Linux version 3.10.14 1.由於每次開發板開機的網卡eth0的物理地址都是隨機的. 然後在網上找到可以通過命令行實現設置mac物理地址: 然後帶著好奇,想看看命令行ifconfig是如何與內核交互的,想試試如何直接通過內核自動設置MAC. 2.分析介紹 因為ifcon ...
  • 1. 首先利用ls命令,找到Ubuntu安裝在哪個磁碟分區; 比如輸入ls後我的機器列出的磁碟分區信息如下: (hd0),(hd1),(hd1,gpt3),(hd1,gpt2),(hd1,gpt1) 查找包含grub.cfg文件的分區 2. 找到Linux的/boot分區,以及/根分區所在的磁碟位置 ...
  • 取出一段數據後,需要獲取指定行 ...
  • 今天在發現了這麼個有趣的東西分享給大家,我們需要一個叫cmatrix的小程式,下麵寫出步驟 1 :依賴環境 yum -y install gcc ncurses-devel 2 :下載程式 wget https://birdteam.net/wp-content/uploads/2017/08/20 ...
  • 內碎片:記憶體固定分區的時候,會發生內碎片。因為記憶體固定分區中,一個作業占用一個或者幾個分區,所以可能出現分配的分區大於所需要的記憶體空間,出現內碎片。但是固定分區不會出現外碎片。 外碎片:在動態分區過程中,動態分區過程一般使用匹配演算法進行分配記憶體(最先匹配法,下次匹配法,最佳匹配法,最壞匹配法),這樣 ...
  • 升級2.7.3使用命令./configure --prefix=/usr/local/python2.7.3時,出現以下錯誤:checking build system type... x86_64-unknown-linux-gnuchecking host system type... x86_ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...