23 MySQL是怎麼保證資料不丟的?

2021-09-26 08:39:39 字數 2308 閱讀 6448

只要保證redo log和binlog持久化到磁碟,就能確保mysql異常重啟後資料可以恢復。

binlog的寫入邏輯比較簡單:事務執行過程中,先把日誌寫到binlog cache,事務提交的時候,再把binlog cache寫到binlog檔案中。

系統給binlog cache分配了一片記憶體,每個執行緒乙個,引數binlog_cache_size用於控制單個執行緒binlog cache所佔記憶體的大小。如果超過了這個引數規定的大小,就要暫存磁碟。

事務提交的時候,執行器把binlog cache裡的完整事務寫入到binlog中,並清空binlog cache。

每個執行緒都有自己的binlog cache,但是共用乙份binlog檔案。

write和fsync的時機,由引數sync_binlog控制:

sync_binlog=0,每次提交事務只write,不fsync;

sync_binlog=1,每次提交事務都會fsync;

sync_binlog=n(n>1),每次提交事務都write,但累積n個事務後才fsync。

實際場景中,比較常見的是是將其設定成100~1000中的某個數值。這樣對應的風險是:如果主機發生異常重啟,會丟失對應數值的binlog日誌。

事務執行過程彙總,生成的redo log先寫到redo log buffer中。

每次生成後不需要直接持久化到磁碟。

事務還沒提交的時候,有可能redo log buffer中的部分日誌也有可能被持久化到磁碟。

redo log可能存在的三種狀態:

三種狀態分別是:

存在redo log buffer中,物理上是在mysql程序記憶體中,就是圖中的紅色部分;

寫到磁碟(write),但是沒有持久化(fsync),物理上是在檔案系統的page cache裡面,圖中中黃色部分;

持久化到磁碟,對應的hard disk,圖中綠色部分。

寫到redo log很快,write到page cache也差不多,持久化到磁碟的速度就慢多了。

為了控制redo log的寫入策略,innodb提供了innodb_flush_log_at_trx_commit引數,有三種可能取值:

0,每次提交事務都只是把redo log留在redo log buffer中;

1,每次提交事務都將redo log直接持久化到磁碟;

2,每次提交事務都都只是把redo log寫到page cache。

innodb有乙個後台執行緒,每隔1秒,會把redo logbuffer中的日誌,呼叫write寫到系統的page cache,然後條用fsync持久化到磁碟。

注意:事務執行過程的redo log也是直接寫在redo log buffer中的,這些redo log也會被後台執行緒一起持久化到磁碟,就是說,乙個沒有提交的事務的redo log,也是可能已經持久化到磁碟的。

除了後台執行緒,還有兩種場景也會讓乙個沒有提交的事務的redo log寫入到磁碟中:

redo log占用的空間即將達到innodb_log_buffer_size一般的時候,後台執行緒會主動寫盤。注意,由於事務沒有提交,這個寫盤動作只是write,沒有呼叫fsync,就是只留在了檔案系統的page cache。

並行的事務提交的時候,順帶將這個事務的redo logbuffer持久化到磁碟

mysql的「雙1」配置,指的是sync_binlog和innodb_flush_log_at_trx_commit都設定成1,意思是,乙個事務完整提交前,需要等待兩次刷盤,一次是redo log(prepare階段),一次是binlog。

組提交機制

如果mysql出現了效能瓶頸,而且瓶頸在io上,可以通過哪些方法來提公升效能:

設定binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count引數,減少binlog的寫盤次數。這個方法是基於「額外的故意等待」來實現的,可能會增加語句的響應時間,但沒有丟失資料的風險。

將sync_binlog設定為大於1的值(比較常見的是100~1000)。這樣的風險是,主機掉電時會丟失binlog日誌。

將innodb_flush_log_at_trx_commit設定為2,這樣的風險是,主機掉電的時候會丟失資料。

不建議將innodb_flush_log_at_trx_commit設定成0。

23 MySQL是怎麼保證資料不丟的?

其實,binlog 的寫入邏輯比較簡單 事務執行過程中,先把日誌寫到 binlog cache,事務提交的時候,再把 binlog cache 寫到 binlog 檔案中。乙個事務的 binlog 是不能被拆開的,因此不論這個事務多大,也要確保一次性寫入。這就涉及到了 binlog cache 的儲...

MySQL 怎麼保證資料不丟?

mysql怎麼保證資料不丟?redo log 的寫入流程是怎麼樣的,如何保證 redo log 真實地寫入了磁碟 binlog的寫入邏輯 事務執行過程中,先把日誌寫到 binlog cache,事務提交的時候,再把 binlog cache 寫到 binlog 檔案中。乙個事務的binlog是不能被...

2 3 mysql儲存 CSV插入資料

上一節,我們大致過了一些mysql儲存引擎為csv型別的table檔案是如何儲存的。那麼這一節,我們來看看一條insert語句是如何執行的,並且落到csv檔案中的。看了很多現在網上的原始碼分析,都是發現5.x與8.0 上差距還是挺大的。mysql insert into user1 values 1...