MySQL的零複製技術

千鋒IT教育發表於2022-12-05


1.需要了解Buffer 與 cache 的區別

Bbuffer 與 Cache 非常類似,因為它們都用於儲存資料資料,被應用層讀取位元組資料。在很多場合它們有著相同的概念:

首先從翻譯上,Buffer應該翻譯為“緩衝”,Cache應該翻譯為“快取”,兩個完全不是一個東西。

在硬體這一層看,Buffer應該為記憶體,Cache為CPU整合的告訴快取。

Buffer為了讓不同速度的裝置能夠同步,建立的一個緩衝區域,寫進Buffer的資料是為了從中拿出寫入其他裝置。

Cache是為了提高讀取速度,將經常或馬上需要的資料預讀到快取中,寫進Cache的資料是為了其他裝置從中去讀取。

從軟體這一層來說,Buffer是塊裝置的緩衝,Cache是檔案系統的快取。以Linux為例,

Buffer(Buffer Cache)以塊形式緩衝了塊裝置的操作,定時或手動的同步到硬碟,它是為了緩衝寫操作然後一次性將很多改動寫入硬碟,避免頻繁寫硬碟,提高寫入效率。

Cache(Page Cache)以頁面形式快取了檔案系統的檔案,給需要使用的程式讀取,它是為了給讀操作提供緩衝,避免頻繁讀硬碟,提高讀取效率。

總而言之,Buffer裡面的東西是為了寫到別處去,Cache裡面的東西是為了給別處讀。

Buffer 與 Cache 的用途有所不一定:

  • Buffer 的主要目的是在不同應用、執行緒、程式之間共享位元組資料,例如為了讓不同速度的裝置能夠進行資料同步,就會使用共享 Buffer;
  • Cache 的主要目的是提高位元組資料的讀取/寫入速度,例如根據時間區域性性、地址區域性性作業系統提供 page cache 機制;

當然,在很多場合下 Buffer 與 Cache 有著相同的語義,因此我們可以認為緩衝區既用於提高讀寫速度,又用於資料共享與同步。

  1. MySQL 緩衝區設計

MySQL 的緩衝區設計如下圖所示:



如上圖所示,MySQL 在不同層次使用了與快取機制不同的配套技術。其中有:

  • 應用層:
    • Redo Log Buffer:對寫操作進行快取,用於實現 MySQL InnoDB 的事務性;
    • InnoDB Buffer Pool:用於對 MySQL table 的資料進行快取。讀記憶體而不是磁碟,透過減少磁碟讀操的方式提高讀操作效能;寫記憶體而不是磁碟,透過減少磁碟寫操的方式提高寫操作效能;
  • 作業系統的 VFS(Virtual file system,虛擬檔案系統)層:
    • Page Cache:作業系統透過快取以及預讀機制對檔案系統中的 block 基於 page 進行快取管理;
    • Direct Buffer:當使用 Direct I/O 提供的相關 API 時,作業系統不再提供基於 Page Cache 機制的快取,而是直接使用 Direct Buffer;
  • 磁碟的 Disk Buffer:磁碟也可以提供磁碟快取,通常在 MySQL 中會關閉磁碟快取,我們僅僅需要了解有 Disk Buffer 這一概念即可。
  1. Write Through/Back 與 Direct I/O

Write Through 與 Write Back 指的是在使用記憶體空間作為快取的應用在處理寫操作時是否直接落盤:

  • Write Through:寫操作"穿過"快取區直接落盤,這種策略能夠確保資料不會因為當機而丟失記憶體緩衝區的資料;
  • Write Back:一次寫操作僅僅更新了記憶體快取區中的資料,資料落盤通常透過間隔一個時間進行落盤一次;

MySQL 為此提供了一些引數來控制 Page Cache 資料落盤的具體行為,例如:

(1)innodb_flush_log_at_trx_commit

innodb_flush_log_at_trx_commit 引數用於控制基於 Page Cache 的 Redo Log Buffer 的資料落盤機制。此引數用於控制以下兩個特性之間的平衡:

1、嚴格的事務管理機制;

2、事務提交 commit 操作執行時的高效能;

innodb_flush_log_at_trx_commit 有三個可選配置值:

  • 1(預設值):每次事務提交時都日誌必須重新整理到磁碟上,提供了最可靠的事務性保證;
  • 0:日誌每間隔 1 秒重新整理到磁碟上,這意味著在快取中還沒有來得及重新整理到磁碟上的資料在當機時會丟失;
  • 2:日誌在事務提交後以及每間隔 1 秒重新整理到磁碟上,這意味著在快取中還沒有來得及重新整理到磁碟上的資料在當機時會丟失;

注意事項:配置 0 與 2 並不能保證 100% 每間隔一秒重新整理到磁碟一次,這是因為 DDL 的修改以及 InnoDB 活動可能會導致日誌重新整理更頻繁。另一方面,由於事務排程問題,重新整理頻率甚至會降低。

重新整理頻率預設為 1 s,由引數 innodb_flush_log_at_timeout 進行配置。

(2)innodb_flush_method

innodb_flush_method 引數同時控制 redo log buffer 和 innodb buffer pool 緩衝區重新整理策略,其中:

  • log files:redo log buffer 是 log files 在記憶體中的快取區, log files 是磁碟上的 Redo Log 檔案;
  • data files:innodb buffer pool 是 data files 在記憶體中的快取區,data files 是磁碟上的資料檔案(B+tree);

innodb_flush_method 引數目前有 6 種可選配置值:

  • fdatasync;
  • O_DSYNC
  • O_DIRECT
  • O_DIRECT_NO_FSYNC
  • littlesync
  • nosync

  • 這裡只討論 Unix-like 作業系統,而不討論 Windows 系統。

其中,littlesync 與 nosync 僅僅用於內部效能測試,並不建議使用。

  • fdatasync,即取值 0,這是預設配置值。對 log files 以及 data files 都採用 fsync 的方式進行同步;
  • O_DSYNC,即取值 1。對 log files 使用 O_SYNC 開啟與重新整理日誌檔案,使用 fsync 來重新整理 data files 中的資料;
  • O_DIRECT,即取值 4。利用 Direct I/O 的方式開啟 data file,並且每次寫操作都透過執行 fsync 系統呼叫的方式落盤;
  • O_DIRECT_NO_FSYNC,即取值 5。利用 Direct I/O 的方式開啟 data files,但是每次寫操作並不會呼叫 fsync 系統呼叫進行落盤;

補充說明:以 O_SYNC 方式開啟檔案意味著檔案的每一次寫操作都直接導致將資料本身以及後設資料重新整理到磁碟上。

為什麼有 O_DIRECT 與 O_DIRECT_NO_FSYNC 配置的區別?

首先,我們需要理解更新操作落盤分為兩個具體的子步驟:①檔案資料更新落盤②檔案後設資料更新落盤。O_DIRECT 的在部分作業系統中會導致檔案後設資料不落盤,除非主動呼叫 fsync,為此,MySQL 提供了 O_DIRECT 以及 O_DIRECT_NO_FSYNC 這兩個配置。

如果你確定在自己的作業系統上,即使不進行 fsync 呼叫,也能夠確保檔案後設資料落盤,那麼請使用 O_DIRECT_NO_FSYNC 配置,這對 MySQL 效能略有幫助。否則,請使用 O_DIRECT,不然檔案後設資料的丟失可能會導致 MySQL 執行錯誤。

  1. MySQL 日誌的重新整理策略

MySQL 日誌重新整理策略透過 sync_binlog 引數進行配置,其有 3 個可選配置:

  • sync_binlog=0:MySQL 應用將完全不負責日誌同步到磁碟,將快取中的日誌資料重新整理到磁碟全權交給作業系統來完成;
  • sync_binlog=1:MySQL 應用在事務提交前將快取區的日誌重新整理到磁碟;
  • sync_binlog=N:當 N 不為 0 與 1 時,MySQL 在收集到 N 個日誌提交後,才會將快取區的日誌同步到磁碟。

事實上,這個引數也用於控制日誌是透過 Write Through 還是 Write Back 策略重新整理到磁碟上。

注意事項:使用 Page Cache 機制的資料刷盤機制,即使基於同步策略,即每次寫操作都要求資料直接落盤,但在資料落盤之前,資料總是先要寫於 Page Cache 中,再將 Page Cache 中的具體 Page 重新整理到磁碟上。

  1. MySQL 的典型配置
  • innodb_flush_log_at_trx_commit 引數配置為 1:Redo Log 走 Page Cache,並且每次寫操作的日誌在事務提交前都透過 fsync 重新整理到磁碟;
  • innodb_flush_method 引數配置為 O_DIRECT:InnoDB Buffer Pool 走 Direct I/O,並且每次寫操作導致的檔案資料(包括檔案後設資料)都透過 fsync 系統呼叫重新整理到磁碟;

寫一條 redo log 涉及到的步驟有:

  • 日誌寫入 Redo Log buffer;
  • 日誌寫入 Page Cache;
  • 透過系統呼叫 fsync 將 Page Cache 中的髒頁重新整理到磁碟;
  • 日誌提交;

修改表的一行記錄涉及到的步驟有:

  • 更新後的資料寫於 InnoDB Buffer Pool;
  • 定時進行如下邏輯(非同步進行):
    • InnoDB Buffer Pool 髒資料進行重新整理,透過檔案的 write 方法進行;
    • 檔案的 write 方法直接導致資料寫於磁碟上;
    • 定時進行檔案的 fysnc 呼叫,確保檔案後設資料寫於磁碟上;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70023145/viewspace-2926794/,如需轉載,請註明出處,否則將追究法律責任。

相關文章