MySQL中事務:html
ACID:sql
都是恢復操做:數據庫
記錄內容不一樣:數組
讀取方式不一樣:緩存
redo-在事務中的應用安全
1.基本概念性能
【事務持久性:D】-- 【重作日誌來實現】ui
【持久性構成】:1.重作日誌緩衝(redo log buffer) ,是易失的 2.重作日誌文件(redo log file),是持久的spa
【持久性原理】:InnoDB是事務的存儲引擎,經過Flush Log at Commit機制實現事務的持久性。即:當事務提交(Commit)時,必須先將事務的全部日誌(這裏只重作日誌)寫入到重作日誌文件中,進行持久化,待事務的commit完成纔算完成。操作系統
【事務的全部日誌】:在InnoDB中,事務的全部日誌有兩部分:redo log 和 undo log
【fsync操做】:爲了確保每次重作日誌都寫入重作日誌文件,在將重作日誌緩衝寫入重作日誌文件後,InnoDB存儲引擎都須要調用一次fsync操做。
【innodb_flush_method = O_DIRECT/NULL】: 控制InnoDB數據文件和redo log 文件打開,刷寫模式。
1.設置爲NULL時,默認是:fsync選項。過程:重作日誌緩衝先寫入文件系統緩存,再進行fsync(將日誌刷新到重作日誌文件 )操做。依賴磁盤的性能。
2.設置爲O_DIRECT,過程:調用用O_DIRECT打開數據文件, 而後調用:fsync(),將全部刷新到數據和log文件中。不通過操做系統緩存,避免兩次寫操做。
【非持久性】:經過手工設置非持久性來提升數據庫性能。
原理:事務提交時,日誌不寫入重作日誌文件,而是等待一個週期後,再執行fsync操做。不是強制每次提交都fsync,能夠顯著提升性能。
弊端:若是數據庫發生宕機,因爲部分日誌未刷新到磁盤,會丟失最後一段的事務。
【innodb_flush_log_at_trx_commit = 0/1/2】:該參數控制重作日誌刷新到磁盤的策略。
1 : 默認是1,表示事務提交時必須調用一次fsync,<redo log刷新條件之一:事務提交前必刷新到日誌文件>。遵循ACID的持久性。
0 : 事務提交時,不進行寫重作日誌操做.寫的操做僅在master Thread中完<redo log 刷新條件之二>,大概每隔1秒執行一次fsync操做.在1秒內有數據庫宕機丟數據的風險.
2 : 寫重作日誌文件,但僅僅寫入文件系統緩存中,不進行fsync操做。僅數據庫宕機系統正常,不會丟數據。 系統宕機,緩存中未刷新到重作日誌文件的那部分事務會丟失.
總結:0和2能提升事務提交性能,可是這種狀況喪失了事務的ACID特性,所以在大量執行insert操做時,在最後執行一次commit操做。這樣回滾時能夠回滾到事務最開始的狀態.
Innodb存儲引擎使用中,爲了遵循持久性和一致性,關於複製的設置:
1.若是啓用二進制日誌(binlog),設置: sync_binlog=1;
2.同時也設置: innodb_flush_log_at_trx_commit=1.
【sync_binlog = N】:
N=0,事務提交後,不作fsync之類的磁盤同步指令,刷新binlog_cache到磁盤文件,而是讓文件系統自行決定什麼時間同步。性能高,可是有丟失數據的風險.
N=1,1次事務提交後,執行fsync操做,將binlog chace同步到磁盤文件。這種選擇是最安全的,可是是最慢的.
【binlog和redo log比較】:
1.產生層面不一樣
redo log: 是在存儲引擎層產生,只針對InnoDB存儲引擎
binlog:在數據庫上層產生的.MySQL中任何存儲引擎對數據庫的更改都會產生二進制日誌.
2.記錄內容形式不一樣
redo log: 是物理格式的日誌,記錄的是對於每一個頁的修改.
binlog: 是一種邏輯日誌,記錄的是sql語句.
3.寫入磁盤時間不一樣
redo log: 在事務進行中不斷的寫入.不隨事務的提交而提交,不是順序寫入的.
binlog: 在事務提交後進行寫入.
2.日誌塊的結構
在InnoDB存儲引擎中,重作日誌都是以512字節進行存儲的.也就是說重作日誌緩衝,重作日誌文件都是以塊(block)的方式進行保存.稱爲:重作日誌塊(redo log block),大小:512字節.
若是一個頁中產生的重作日誌大於512字節,就分割成多個重作日誌塊就行存儲.
重作日誌塊的大小和磁盤扇區的大小同樣,512字節,所以重作日誌的寫入能夠保證原子性,不須要doublewrite技術.
日誌塊的組成:日誌自己,日誌塊頭(log block header),日誌塊尾(log block tailer)
Log Block Header 解析:
LOG_BLOCK_HDR_NO:4字節
log buffer由log block組成,在內部就像一個數組,而LOG_BLOCK_HDR_NO,用來標記這個數組中的位置。改制必須大於0,容許最大2G;若是在日誌刷新寫入段時,是第一個日誌塊,最高位就設置成1.
LOG_BLOCK_DATA_LEN:2字節
表示LOG_BLOCK所佔用的大小,被寫滿時,該值爲:0x200,表示所有block空間,即佔用512字節。
LOG_BLOCK_FIRST_REC_GROUP:佔用2字節
表示LOG_BLOCK中第一個日誌所在的偏移量。若是LOG_BLOCK_FIRST_REC_GROUP=LOG_BLOCK_DATA_LEN 表示log block不包含新的日誌。
LOG_BLOCK_CHECKPOINT_NO:4字節
表示:LOG_BLOCK最後被寫入時的檢查點。若是此時log block還沒寫滿,只能等下次log flush 時,纔會更新。
關於一個事務佔用兩個log block的圖:
事務T1的重作日誌佔用:696字節
事務T2的重作日誌佔用:100字節
有圖知道:事務T1 696字節,佔用兩個log block,左側的log block中 LOG_BLOCK_FIRST_REC_GROUP=12,即第一個日誌開始的位置。
在第二個block中,因爲包含了T1的重作日誌,所以事務T2的重作日誌纔是block中的第一個日誌,即 LOG_BLOCK_FIRST_REC_GROUP=(12+200)=212
3.重作日誌組(log group)
log group爲重作日誌組,裏面有多個重作日誌文件。源碼中支持log group的鏡像功能,但已禁用了,所以InnoDB存儲引擎實際只有1個log group。
log group 是邏輯上的概念!!!
重作日誌存儲的就是以前在log buffer中保存的塊,所以也是根據塊的方式進行物理存儲的管理。block=512bytes。
InnoDB存儲引擎運行過程當中, log buffer根據必定的規則將log block刷新到磁盤:
1.事務提交時
2.當log buffer中一半的空間已經被使用
3.log checkpoint時
redo log file的寫入順序:
log block 寫入追加到redo log file的最後部分,當一個redo log file寫滿時,會寫入下一個redo log file。 這種方式:round-robin.
看起來是順序的,其實否則,除了保存log buffer刷新到磁盤的log block,還保存了一些其餘信息,這些信息佔:2KB,即redo log file 的前2KB不保存log block的信息。
2KB的信息:保存 4 * 512字節的 塊。
名稱 | 大小(字節) |
log file header |
512 |
checkpoint1 |
512 |
空 |
512 |
checkpoint2 |
512 |
上述信息只在log group的第一個redo log file裏存儲,其他file留空,這也就是說 寫入不是順序的!以下圖:
4.重作日誌的格式
5.LSN
LSN : Log Sequence Number的縮寫,表明日誌序列號,單位:字節。在innodb存儲引擎中佔有8字節,單調遞增。
LSN : 表示的含義
LSN 表示事務寫入重作日誌的字節總量。例如,當前重作日誌的LSN是1000,事務T1寫入了100字節的重作日誌,LSN就變成1100,又有事務T2寫入200字節的重作日誌,那麼LSN變成:1300.
LSN不只記錄在重作日誌中,還記錄在頁中。每一個頁的開頭部有一個FIL_PAGE_LNS,記錄該頁的LSN。
頁中的LSN表示:該頁最後刷新時LSN的大小。
重作日誌記錄的是每一個頁的物理更改日誌,所以頁中的LSN用來判斷是否須要進行恢復操做。例如:頁的LSN爲:10000,數據庫啓動時,寫入重作日誌的LSN:13000,代表該事務已經提交,數據庫須要恢復;重作日誌中的LSN小於頁中的LSN,不須要進行重作,由於頁中的LSN表示已經刷新到該位置。
經過:SHOW ENGINE INNODB STATUS\G來查看LSN的狀況
---
LOG
---
Log sequence number 47324552 ----------------->表示當前的LSN
Log flushed up to 47324552 ----------------->表示刷新到重作日誌的LSN
Pages flushed up to 47324552 ----------------->表示刷新到磁盤的LSN
Last checkpoint at 47324552
Max checkpoint age 80826164
Checkpoint age target 78300347
....
上述的3個值,生產環境中多是不一樣的:由於一個事務從重作日誌緩衝刷新到重作日誌文件,並不僅是在事務提交時發生,每秒都會有重作日誌緩衝刷新到重作日誌文件的操做。
6.恢復
InnoDB存儲引擎在啓動時,無論上次數據庫是否正常關閉,都會嘗試進行恢復。重作日誌是物理日誌,恢復時比較快。
checkpoint 表示已經刷新到磁盤上的LSN。
例子:redo log file 記錄的LSN:13000,刷新到磁盤上的LSN:10000,數據庫在10000處宕機,恢復時,只需恢復10000~13000的部分。
--完結