保證:如果客戶端收到事務成功的訊息,事務就一定持久化了;
保證:如果客戶端收到事務失敗(比如主鍵衝突、回滾等)的訊息,事務就一定失敗了;
保證:如果客戶端收到,執行異常的訊息,應該通過查詢當前狀態來繼續後續的邏輯,此時資料庫只需要保證內部一致(資料和日誌之間,主庫和備庫之間);
通俗的來說,crash-safe 保證了,資料庫可以實現恢復到完整日誌範圍內,任意一秒的狀態;
mysql 是通過 完整的 redo log 和 bin log 來保證 crash-safe的,所以需要保證完整的日誌,且磁碟儲存;
bin log 是server層的日誌,而redo log 是引擎層的日誌,並且是 innodb 引擎特有的;
bin log 是邏輯日誌,記錄的是sql語句的原始邏輯,比如「 給 id=2 的這一行的 c 欄位加 1 」,而 redo log 是物理日誌,記錄的是 」在某個資料頁上做了什麼修改」;
binlog 是追加寫入的,是指寫到一定大小後,會切換到下乙個,不會覆蓋以前的日誌;而 redo log 是迴圈寫的,空間固定會用完,用完後需要將記憶體頁重新整理到磁碟(注意不是 redo log 持久化,已經持久化過了),然後擦除部分 redo log 來空出空間;
事務執行過程中,先把日誌寫到 bin log cache,事務提交的時候,再把 bin log cache 寫到 bin log 檔案中,最後通過 fsync 寫入磁碟中,注意,每個執行緒都有自己 bin log cache,但是共用同乙份 bin log 檔案;
write 操作,寫入 bin log 檔案,並不是持久化到磁碟,而 fsync 才是持久化操作;這兩個操作的時機,是由引數 sync_binlog 控制的;
sync_binlog =0 ,表示提交事務只 write,不 fsync;sync_binlog = 1,表示提交事務只 fsync;sync_binlog = n,表示提交事務 write,累積 n 個事務後執行 fsync;設定為n,如果發生異常重啟,會丟失最近 n 個事務的 bin log 日誌;
mysql 執行修改操作,會首先檢測記憶體中是否存在,如果不存在,需要從磁碟中讀入到記憶體中,然後寫記憶體,寫 redo log,此時修改操作正常返回,最後在資料庫空閒時,將記憶體資料寫入到磁碟,這個過程被稱為 wal,隨讓 redo log 持久化也需要 io 操作,但這種順序 io 比 隨機 io 速度快很多;
redo log 的持久化策略,是通過設定 innodb_flush_log_at_trx_commit 引數,設定為 0 的時,表示事務提交時,只把 redo log 留在 redo log buffer 的記憶體空間中 ;設定為 1 的時,表示事務提交時,將 redo log 直接持久化到磁碟;設定為 2 的時候,表示事務提交時,只把 redo log 寫到 page cache;
innodb 有乙個後台執行緒,每隔 1 秒,就會把 redo log buffer 中的日誌,呼叫 write 寫到檔案系統的 page cache,然後呼叫 fsync 持久化到磁碟。
redo log 是通過二階段提交來寫入的,會和 bin log 一起,保證同時提交;
建議常見 tb 級別的磁碟,將 redo log 大小設定為 4 個檔案,每個檔案 1 gb,避免 redo log 頻繁寫滿,導致刷髒頁;
redo log 是在 mysql 崩潰後恢復時使用,正常刷髒頁的過程,只需要將記憶體資料頁,merge 到磁碟資料頁即可;
redo log 的引數 innodb_flush_log_at_trx_commit 設定為 1 的時候,表示每次事務的 redo log 都直接持久化到磁碟,建議設定成 1,保證 mysql 異常重啟之後資料不丟失;
同樣 bin log 的引數 sync_binlog 設定成 1 的時候,表示每次事務的 binlog 都持久化到磁碟,建議設定成 1,保證 mysql 異常重啟之後 binlog 不丟失;
分析更新語句 update t set c = c + 1 where id = 2 的執行流程,sql語句到達執行器,呼叫儲存引擎介面,獲取 id = 2 這一行;
儲存引擎,判斷id是主鍵,呼叫索引樹搜尋,找到這一行,如果在記憶體中就直接返回,否則從磁碟中讀入記憶體,再返回;
儲存引擎,首先會將更新操作 c + 1 寫入記憶體,同時記錄到 redo log,此時該條 redo log 處於 prepare 狀態,最後告知執行器,完成更新可以提交事務;
執行器會生成該操作的 bin log,然後呼叫儲存引擎的提交事務介面,此時儲存引擎就會將,該條 redo log 修改為 commit 狀態,操作完成;
這裡使用了兩階段提交,只有 redo log 為 commit 狀態的,才會真正執行到磁碟中,這樣保證了 bin log 和 redo log 的一致性;
考慮下,如果 redo log 處於 prepare 狀態,bin log 完成寫操作,此時 mysql 異常重啟後,對於 redo log 的處理會判斷,如果 redo log 是 prepare,沒有 commit,但 bin log 是完整的,就會提交該事務;
innodb 更新時,會寫記憶體和寫 redo log,此時記憶體資料頁和磁碟資料頁是不一致的,innodb 查詢時,如果記憶體中有結果,就直接返回,如果記憶體中沒有,就會去磁碟查詢,並將該資料頁,載入到記憶體中;其中記憶體和磁碟不一致的,將記憶體中的這部分資料頁稱為髒頁;
注意髒頁,並不是指記憶體中資料不對,而是磁碟資料落後,需要將記憶體資料頁 flush 到磁碟;
flush 操作觸發有幾種情況,一種是 redo log 寫滿了,另一種是 系統記憶體不足,需要 flush 髒頁到磁碟來空出記憶體,注意不能因為 redo log 有記錄就直接丟棄髒頁,因為這種落磁碟,能保證下次從磁碟載入到記憶體中的資料一定是正確的;第三種是,mysql 空閒和 mysql 正常關閉時;
如果平時執行很快的sql語句,偶爾執行慢了,可能是髒頁 flush 到磁碟的過程消耗了時間;
innodb flush 髒頁,會用到 innodb_io_capacity 引數,建議設定成 磁碟的 iops;引數 innodb_max_dirty_pages_pct 是髒頁比例上限,預設是75%,多關注髒頁比例,不用使其經常接近75%;
引數 innodb_flush_neighbors 可以控制 flush 髒頁的 「連坐」 機制,在ssd設定,建議設定為0;
假設,想將資料恢復到前一天某個時間點,首先 bin log 會定期備份,找到最近的一次全量備份,然後從該備份來恢復資料;
將該備份恢復到臨時庫,然後從該時間點開始,將 bin log 依次取出,取到想要恢復的時間點,然後依次恢復,最後將想要恢復的資料從臨時庫取出,恢復到線上庫中;
SpringBoot 三 日誌檔案
總結 1 springboot底層使用slf4 logback的方式進行日誌記錄 2 springboot將其他的日誌檔案都替換成slf4.3 中間包替換?4 如果我們要引入其他框架?一定要把這個框架的預設配置移除掉 要不包名類名一直則衝突 如下圖 springboot日誌檔案配置預設是info級別...
練習指令碼三 日誌清除
日誌清除 bin bash 清除日誌指令碼,版本2 log dir var log root uid 0 uid為0的時候,使用者才具有root使用者的許可權 判斷是否使用root使用者來執行 if uid ne root uid then echo must be root to run this...
Nginx初學(三)日誌的配置
1 進入到nginx的日誌目錄,我們可以看到下圖的三個檔案 其中nginx.pid中存放的是程序號,access.log是訪問日誌,error是錯誤日誌。2 我們開啟配置檔案,可以設定自己的日誌檔案。如下,配置好後儲存,重啟nginx。server access log logs wuaipic.l...