Mysql如何保證資料不會丟失

2021-10-05 01:45:30 字數 2375 閱讀 5175

簡單來說就是依靠redo log和binlog保證持久化到磁碟後就可以保證,異常重啟資料可以正常恢復;這裡主要說下這兩個log的寫入機制。

乙個事務執行的過程中,會先把日誌寫入到binlog cache中,事務提交的時候再把binlog cache中的日誌寫到binlog中。系統給binlog cache分配了一片記憶體,每個執行緒乙個,其大小由引數(binlog_cache_size)控制,超出這個大小就要暫存到磁碟,事務提交時寫入binlog,再清除binlog cache中的資料;雖然每個執行緒都有自己的binlog cache但是都共用乙份binlog檔案

binlog寫入磁碟,其實分為兩個步驟:1、先write到page cache 2、再fsync持久化到磁碟;真正占用io的還是fsync,所以由引數sync_binlog控制寫入時機,具體:

常見的是將引數值定義為10-100中的值,也會有丟失近n個事務的binlog

redo log同樣事務執行過程中,會先把redo log寫入到redo_log buffer中,會在特定的時間將redo_log buffer中的日誌寫入到磁碟中,innodb提供了引數innodb_flush_log_at_trx_commit,控制redo_log的寫入策略:

設定為0的時候,表示每次事務提交時都只是把redo log留在redo log buffer中;

設定為1的時候,表示每次事務提交時都將redo log直接持久化到磁碟;

設定為2的時候,表示每次事務提交時都只是把redo log寫到page cache。

innodb有乙個後台執行緒每隔1s就會呼叫write把redo_log buffer中的日誌寫到page cache再呼叫fsync把日誌持久化到磁碟,所以會出現某些事務未提交也會被持久化到磁碟。

還有兩種場景也會出現未提交事務被持久化到磁碟:

1、當redo_log buffer的大小達到innodb_log_buffer_size一半時,此種情況只write 不fsync

2、當兩個並行的事務,乙個事務提交時,另乙個也有可能被持久化到磁碟,當然具體依賴於innodb_flush_log_at_trx_commit引數的設定

根據兩階段提交(後面會說下兩階段提交)時序上redo_log先prepare 再寫binlog最後再把redo_log commit。

如果把兩種日誌都配成「雙1」即:sync_binlog和innodb_flush_log_at_trx_commit都設定成1,就是說一次事務提交需要刷兩次盤(一次是redo_log的perpare階段,一次是binlog)實則不然,這裡就用到了組提交;日誌邏輯序號lsn就對應redo_log的乙個個寫入點,每次寫入length個redo_log其長度就加length;最先到達的事務被選為組長,組長寫入磁碟的時候會帶上組中最大的lsn(lsn會寫到資料頁中來確保資料頁不會多次重複的執行redo_log),剩餘小於最大lsn的事務都會直接返回;故而乙個組中組員越多越節約io。

--兩階段提交:1、寫redo_log,處於prepare階段 2、寫binlog 3、提交事務,處於commit階段

--「拉長」兩階段提交:1、redo_log prepare write 2、binlog write 3、redo_log prepare fsync 4、binlog fsync 5、redo_log commit,write(提交事務)如此一來如果前面事務寫完第四步binlog fsync也可以組提交,一般binlog的組提交效果沒有那麼好是因為第三步比較快;當然也可以用引數來提公升組提交的效果:

binlog_group_commit_sync_delay引數,表示延遲多少微秒後才呼叫fsync;

binlog_group_commit_sync_no_delay_count引數,表示累積多少次以後才呼叫fsync。

這兩者滿足任意乙個都會觸發fsync

這就可以很好的解釋了雖然事務的提交每次都要redo_log和binlog磁碟的讀寫次數依然沒有變少:

redo log 和 binlog都是順序寫,磁碟的順序寫比隨機寫速度要快;

組提交機制,可以大幅度降低磁碟的iops消耗。

如此一來,如果分析到資料庫的出現了效能的瓶頸,並且瓶頸在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。這樣做的風險是,主機掉電的時候會丟資料。

分析完幾篇日誌的文章統一總結吧。

參考林曉彬《mysql45講》

Kafka 如何保證訊息不會丟失

kafka 提供了資料高可靠的特性,但是如果使用不當,你可能無法享受到這一特性,今天我們就來看看如何正確的使用kafka 保證資料的不會丟失吧!kafka為生產者生產訊息提供了乙個send msg 方法,另有乙個過載的方法send msg,callback 當我們通過send msg,callbac...

Redis如何保證系統宕機資料不會丟失

我們都知道 redis 的資料全部在記憶體裡,如果突然宕機,資料就會全部丟失,因此必須有一種機制來保證 redis 的資料不會因為故障而丟失,這種機制就是 redis 的持久化機制。如圖1.1所示,redis 的持久化機制有兩種,第一種是快照,第二種是 aof 日誌。快照是一次全量備份,aof 日誌...

Kafka如何保證資料不丟失

kafka的ack機制 在kafka傳送資料的時候,每次傳送訊息都會有乙個確認反饋機制,確保訊息正常的能夠被收到,其中狀態有0,1,1。producer.type sync request.required.acks 1 producer.type async request.required.ac...