MySQL鎖係列(三)之 redo log
WHY
1)鎖和事務是分不開的,事務和redo又是傻傻分不清楚的
2)事務最重要的是什麼?ACID 又是如何實現的?
* A 原子性
通過redo實現
* C 一致性
通過undo實現
* I 隔離性
通過lock實現
* D 持久性
通過redo和undo實現
redo log 是什麼
- redo 概念
* 學名:重做日誌
* 個人理解:任何事務的操作都會記錄redo日誌,InnoDB引擎獨有,用於恢複數據庫到宕機的位置
- redo 結構
* redo log buffer
1. 日誌會先寫到redo log buffer ,根據製定條件刷新到redo log file
2. 由log block組成
3. 每個log block 512字節,所以不需要double write,因為每次刷新都是原子的
* redo log file
1. redo log的物理文件,一般有2個,大小可配置
2. 由innodb_log_file_size配置,越大越好
3. redo類型是物理邏輯日誌,記錄的是對頁的操作,頁內是邏輯的內容,我們姑且認為就是物理日誌好了,記錄的是對頁的操作
比如:insert 一條記錄,那麼大致內容就會記錄
對space id=3,page no=4 ,offset aa, 日誌內容xx (主鍵索引)
對space id=3,page no=8 ,offset bb, 日誌內容yy (二級索引)
- redo log buffer刷新觸發條件
1. 每秒刷新一次
2. redo log buffer使用大於1/2進行刷新
3. 事務commit(提交)時候進行刷新
a. innodb_flush_log_at_trx_commit=0 : 事務提交時,不刷新redo log buffer
b. innodb_flush_log_at_trx_commit=1 : 事務提交時,將redo log buffer刷新到磁盤(由於redo沒有O_direct,也必須經過操作係統緩存,然後fsync到磁盤)
c. innodb_flush_log_at_trx_commit=2 : 事務提交時,將reod log buffer刷新到os的緩存
- redo log 的重要組成部分
1. redo log 是循環寫入的,寫完一個,寫另一個
2. redo log 的第一個文件的頭部,會記錄兩個512字節的記錄,分別是:checkpoint1 和 checkpoint2,輪詢寫入,互為備份
3. 上麵說的很重要,checkpoint 是寫在redo 日誌裏麵的,checkpoint是什麼,後麵介紹
4. redo 裏麵記錄的是日誌的寫入,裏麵有個很重要的概念叫做 lsn
- lsn 是什麼
* LSN = log sequeuce number , 日誌的序列號,數據庫的邏輯時鍾, 特點是單調遞增
LSN表示事務寫入重做日誌的字節總量
* LSN是什麼?有什麼含義?
---
LOG
---
Log sequence number 86594404775 -- redo log buffer 的lsn,存放在redo log buffer 中 我們稱: redo_mem_lsn
Log flushed up to 86594404775 -- redo log file 的lsn,存放在redo log 中 我們稱: redo_log_lsn
Pages flushed up to 86594404775 -- 最後一個被刷新頁的newest_modification, 這個用的比較少,暫時忽略, 這個存放在date page裏麵
Last checkpoint at 86594404766 -- checkpoint的lsn , 存放在redo log第一個文件的頭部 , 我們稱: cp_lsn
目前看下來lsn有三個含義
1. redo_mem_lsn
2. redo_log_lsn
3. cp_lsn
4. page_lsn: 每個page裏麵頭部都會記錄一個lsn,表示該page最後一次被修改的redo log lsn
以上4個lsn都是互相關聯的
* LSN 有什麼用?
主要用於MySQL重啟恢複
* 恢複的算法如下?
假設: redo_log_lsn = 15000 , cp_lsn=10000 , 這時候MySQL crash了,重啟後的恢複流程如下:
a. cp_lsn = 10000 之前的redo 日誌,不需要恢複: 因為checkpoint之前的日誌已經可以確保刷新完畢
b. 那麼 10000 <= redo_log_LSN <= 15000 的日誌需要結合page_lsn判斷,哪些需要重做,哪些不需要重做。
b.1 redo_log_LSN 日誌裏麵記錄的page 操作,如果redo_log_LSN <= page_lsn , 這些日誌不需要重做,因為page已經是最新的
b.2 redo_log_LSN 日誌裏麵記錄的page 操作, 如果redo_log_LSN >= page_lsn , 這些日誌是需要應用到page 裏麵去的,這一係列操作我們稱為恢複.
c. 舉個例子
如果:redo_log_lsn 11000 , 記錄的是:space id=3,page no=4 的頁的操作,但是這個頁的page_lsn = 11500,那麼說明這個頁的lsn比redo的lsn新,那麼就不需要應用
如果:redo_log_lsn 11000 , 記錄的是:space id=3,page no=4 的頁的操作,但是這個頁的page_lsn = 10500,那麼說明這個頁的lsn比redo的lsn老,那麼需要應用這部分日誌以達到恢複的目的
Write-Ahead Log (WAL)
當一個數據頁被刷新時,必須要求內存中小於該數據頁lsn對應的所有redo日誌,都必須先刷新到磁盤
我們稱為:日誌先行, 保證redo log 日誌必須先於 data page 刷新
Force-log-at-commit
當一個事務進行commit的時候,必須先將該事務的所有日誌寫入到重做日誌文件進行持久化
checkpoint
- 什麼是checkpoint
* 沒有checkpoint的時候,數據庫髒頁都存放在內存中,如果這時候數據庫掛了,那麼redo就需要從頭到尾開始恢複,非常慢
* 有checkpoint的時候,會按照一定的算法進行data page髒頁的刷新, 減少數據庫恢複的時間
a)checkpoint_lsn 表示: 在checkpoint_lsn 之前的redo日誌對應的髒頁都已經刷新到磁盤了
b) 也就意味著,當數據庫重啟恢複的時候,小於checkpoint_lsn的redo日誌不需要再重做,大大的減少了數據庫的恢複時間
- checkpoint種類
* sharp checkpoint
當MySQL正常關閉的時候,需要將所有的髒頁都刷新
* fuzzy checkpoint
為了考慮數據庫的性能,MySQL按照一定算法之刷新部分髒頁
fuzzy checkpoint 觸發條件
- 定時刷新
每10秒,或者每1秒,從髒頁列表中去刷新部分髒頁
- LRU列表的刷新
* buffer pool 內存解釋:
* free list : 表示數據庫開啟時候,MySQL會分配空閑的頁給free list
* LRU list : 當頁被第一次訪問(讀或者寫)的時候,會加入到LRU list
* flush list :當頁變成髒頁的是,會按照第一次被更新的時間(oldest_modification)排序,加入到flush list,flush list裏麵存放的都是指向lru_list的指針,並不占用太多內存
* 刷新
當buffer pool中少於innodb_lru_scan_depth指定的空閑頁時候
會將LRU list中尾端的頁(不常用的頁)進行拿來用,如果是髒頁,則進行checkpoint
- 高水位和低水位的刷新
* checkpoint age = redo_lsn - cp_lsn
低水位 = 75% * 總redo大小
高水位 = 90% * 總redo大小
* 低水位 >= checkpoint age
不需要刷新
* 低水位 <= checkpoint age <= 高水位
會強製進行 checkpoint , 根據flush_list的順序,刷新足夠多的髒頁,讓checkpoint age 小於低水位線
* 高水位 >= checkpoint age
會強製進行 checkpoint , 根據flush_list的順序,刷新髒頁, 讓其滿足 低水位 <= checkpoint age >= 高水位
- 髒頁太多的時候刷新
* innodb_max_dirty_pages_pct
當髒頁數量超過這個比例時候,會強製進行checkpoint
redo 的寫入時機
- binlog的寫入時機
事務結束後,binlog進行寫入並刷新
T1 -> T2 -> T3 -> T4 按照事務的順序執行
- redo的寫入時機
當事務開啟後,第一條dml語句開始執行時,就開始慢慢的寫入並刷新redo
T1_1 -> T2_1 -> T2_2 -> T3_1 -> T1_2 -> *T2 -> *T3 -> *T1
以上列表的分析為:
這個代表事務的開始執行順序是: T1,T2,T3
這個代表事務的結束執行順序是: T2,T3,T1
- commit執行的時間長短,取決於什麼?
根據以上binlog和redo 的寫入時機可以判斷,commit的長短取決於binlog的日誌大小和刷新時間
redo 和 undo
1. 這裏先稍微提一下undo,至於undo 是什麼,後麵介紹
2. undo日誌本身也要寫入到redo裏麵去,這一點非常重要
最後
這裏簡單的介紹了redo的內容,這塊內容非常重要,複製,高可用與之非常密切
這裏麵的checkpoint age可以用來監控,監控這個的目的通過這篇文章我想大家都應該知道了吧
最後更新:2017-06-12 17:02:04