Mysql基礎課三 日誌

2021-10-01 15:43:46 字數 3398 閱讀 8217

保證:如果客戶端收到事務成功的訊息,事務就一定持久化了;

保證:如果客戶端收到事務失敗(比如主鍵衝突、回滾等)的訊息,事務就一定失敗了;

保證:如果客戶端收到,執行異常的訊息,應該通過查詢當前狀態來繼續後續的邏輯,此時資料庫只需要保證內部一致(資料和日誌之間,主庫和備庫之間);

通俗的來說,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...