mysql怎麼保證資料不丟?
redo log 的寫入流程是怎麼樣的,如何保證 redo log 真實地寫入了磁碟 ?
binlog的寫入邏輯:事務執行過程中,先把日誌寫到 binlog cache,事務提交的時候,再把 binlog cache 寫到 binlog 檔案中。
乙個事務的binlog是不能被拆開的,因此不論這個事務多大,也要確保一次性寫入。
系統給 binlog cache 分配了一片記憶體,每個執行緒乙個,引數binlog_cache_size 用於控制單個執行緒內 binlog cache 所佔記憶體的大小。 如果超過了這個引數規定的大小, 就要暫存到磁碟。
事務提交的時候,執行器把 binlog cache 裡的完整事務寫入到 binlog 中,並清空 binlog cache。
每個執行緒有自己 binlog cache,但是共用同乙份 binlog 檔案。
write,指的就是指把日誌寫入到檔案系統的 page cache,並沒有把資料持久化到磁碟,所以速度比較快。
fsync,才是將資料持久化到磁碟的操作。fsync 才佔磁碟的 iops。
write 和 fsync 的時機,是由引數 sync_binlog 控制的:
1.sync_binlog=0 的時候,表示每次提交事務都只 write,不 fsync;
2.sync_binlog=1 的時候,表示每次提交事務都會執行 fsync;
3.sync_binlog=n(n>1) 的時候,表示每次提交事務都 write,但累積 n 個事務後才 fsync。
一般不建議將這個引數設成 0,比較常見的是將其設定為 100~1000 中的某個數值。對應的風險是:如果主機發生異常重啟,會丟失最近 n 個事務的 binlog 日誌。
redo log 三種狀態:
1.存在 redo log buffer 中,物理上是在 mysql 程序記憶體中,就是圖中的紅色部分;
2.寫到磁碟 (write),但是沒有持久化(fsync),物理上是在檔案系統的 page cache 裡面,也就是圖中的黃色部分;
3.持久化到磁碟,對應的是 hard disk,也就是圖中的綠色部分。
innodb 提供了 innodb_flush_log_at_trx_commit 引數,控制 redo log 的寫入策略,有三種可能取值:
1.設定為 0 的時候,表示每次事務提交時都只是把 redo log 留在 redo log buffer 中 ;
2.設定為 1 的時候,表示每次事務提交時都將 redo log 直接持久化到磁碟;
3.設定為 2 的時候,表示每次事務提交時都只是把 redo log 寫到 page cache。
事務執行中間過程的 redo log 也是直接寫在 redo log buffer 中的,這些 redo log 也會被後台執行緒一起持久化到磁碟。也就是說,乙個沒有提交的事務的 redo log,也是可能已經持久化到磁碟的。
還有兩種場景會讓乙個沒有提交的事務的 redo log 寫入到磁碟中:
一種是,redo log buffer 占用的空間即將達到 innodb_log_buffer_size 一半的時候,後台執行緒會主動寫盤。
另一種是,並行的事務提交的時候,順帶將這個事務的 redo log buffer 持久化到磁碟。假設乙個事務 a 執行到一半,已經寫了一些 redo log 到 buffer 中,這時候有另外乙個執行緒的事務 b 提交,如果 innodb_flush_log_at_trx_commit 設定的是 1,那麼按照這個引數的邏輯,事務 b 要把 redo log buffer 裡的日誌全部持久化到磁碟。這時候,就會帶上事務 a 在 redo log buffer 裡的日誌一起持久化到磁碟。
組提交(group commit)機制:
wal 機制主要得益於兩個方面:
redo log 和 binlog 都是順序寫,磁碟的順序寫比隨機寫速度要快;
組提交機制,可以大幅度降低磁碟的 iops 消耗。
如果你的 mysql 現在出現了效能瓶頸,而且瓶頸在 io 上,可以通過哪些方法來提公升效能呢?
可以考慮以下三種方法:
1.設定 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 引數,減少 binlog 的寫盤次數。這個方法是基於「額外的故意等待」來實現的,因此可能會增加語句的響應時間,但沒有丟失資料的風險。
2.將 sync_binlog 設定為大於 1 的值(比較常見是 100~1000)。這樣做的風險是,主機掉電時會丟 binlog 日誌。
3.將innodb_flush_log_at_trx_commit 設定為2。這樣做的風險是,主機掉電的時候會丟資料。
不建議把 innodb_flush_log_at_trx_commit 設定成 0。因為把這個引數設定成 0,表示 redo log 只儲存在記憶體中,這樣的話 mysql 本身異常重啟也會丟資料,風險太大。而 redo log 寫到檔案系統的 page cache 的速度也是很快的,所以將這個引數設定成 2 跟設定成 0 其實效能差不多,但這樣做 mysql 異常重啟時就不會丟資料了,相比之下風險會更小。
23 MySQL是怎麼保證資料不丟的?
只要保證redo log和binlog持久化到磁碟,就能確保mysql異常重啟後資料可以恢復。binlog的寫入邏輯比較簡單 事務執行過程中,先把日誌寫到binlog cache,事務提交的時候,再把binlog cache寫到binlog檔案中。系統給binlog cache分配了一片記憶體,每個...
23 MySQL是怎麼保證資料不丟的?
其實,binlog 的寫入邏輯比較簡單 事務執行過程中,先把日誌寫到 binlog cache,事務提交的時候,再把 binlog cache 寫到 binlog 檔案中。乙個事務的 binlog 是不能被拆開的,因此不論這個事務多大,也要確保一次性寫入。這就涉及到了 binlog cache 的儲...
Kafka如何保證不丟訊息
生產者 producer 呼叫send方法傳送訊息之後,訊息可能因為網路問題並沒有傳送過去。訊息到partition的時候,會分配乙個offset,消費者拉取某個分割槽的訊息後,會自動提交offset,如果這部分訊息還沒有消費,突然掛掉了,這個時候這部分訊息就丟失了 kafka中partition分...