MySQL——日誌、事務、索引

       前提概要:MySQL的原生引擎是MyISAM。因爲MyISAM在日誌層面不支持redo log,在事務層面不支持事務。所以才引入存儲引擎InnoDB。MySQL用的是WAL(write-ahead log)機制,先寫日誌再寫磁盤——這樣子的好處在於可以實現crash safe。先介紹完概念再分析。

日誌篇:

在MySQL引入InnoDB後,redo log和binlog是兩種MySQL的日誌。兩種日誌是獨立的,

1)redo log :

MySQL引入InnoDB後,支持redo log。redo log是“循環”寫入日誌的方式——開闢一個內存區,這個內存區形象的描述成一個,環上有兩個指針,前面的叫寫指針,後面的叫擦除指針。寫指針一直把日誌寫到內存裏,擦除指針把內存數據刪掉,變成新的空閒地方可以使用。所以,當寫指針與探險指針相遇(也就是追趕上了),那就是redo log內已經沒有空閒的地方可以記日誌了。那麼,需要把redo log裏的一部分日誌內容寫入磁盤。這樣子做的好處在於,可以減少磁盤寫操作的數次(據說可以減少一半的量),從而提高數據庫I/O性能效率。

redo log是物理日誌,順序讀寫,不具有持久性——所以沒有binlog的歸檔功能。redo log日誌是記錄未完成的事務日誌。分爲兩個狀態:prepare 和 commit

來一下官方介紹:

The redo log is a disk-based data structure used during crash recovery to correct data written by incomplete transactions. During normal operations, the redo log encodes requests to change table data that result from SQL statements or low-level API calls. Modifications that did not finish updating the data files before an unexpected shutdown are replayed automatically during initialization, and before the connections are accepted.

根據官方描述,我們可以知道redo log是爲了應付系統臨時崩潰恢復用的。後面會詳細介紹。

2)binlog:

binlog的全稱是binary log——二進制日誌。官方描述如下:The binary log contains “events” that describe database changes such as table creation operations or cha4nges to table data. It also contains events for statements that potentially could have made changes (for example, a DELETE which matched no rows), unless row-based logging is used. The binary log also contains information about how long each statement took that updated data. 

binlog是MySQl的server層的歸檔日誌。什麼叫歸檔日誌呢?——歸檔日誌(Archive Log)是非活動的重做日誌備份。通過使用歸檔日誌,可以保留所有重做歷史記錄,當數據庫處於ARCHIVELOG模式並進行日誌切換式,後臺進程ARCH會將重做日誌的內容保存到歸檔日誌中。當數據庫出現介質失敗時,使用數據文件備份,歸檔日誌和重做日誌可以完全恢復數據庫。

binlog用於只記錄對數據庫數據發現變化的操作(update/insert/delete等)(如果是select這種,還有一個query log數據)。因此binlog用於記錄維護數據庫操作和恢復個別數據。

下面用一張圖來解析redo log和binlog的執行順序和遇到crash的時候的恢復邏輯:

redo log處理prepare狀態時,代表執行器執行成功,可以隨時commit數據 。然後執行器生成update操作的binlog,並把binlog寫入磁盤。執行器調用存儲引擎的事務接交接口,把redo log的狀態改成commit,數據才真正提交。

redo log兩個狀態是爲了保證恢復時數據保持一致。假設redo log只有一個狀態,那就有兩種場景:

1)如果是先記錄redo log,再記binlog。那麼在【記redo log完成,還沒成功記binlog】的情況下(即圖中的時刻A),redo log恢復數據時因爲執行器已執行完成,所以C的值爲1。但是binlog沒有任何日誌,所以如果用binlogC的值恢復爲0。兩個日誌恢復出來的數據不一致

2)如果是先記binlog,再記redo log。那麼在【記binlog完成,還沒成功記redo log】的情況下,同理可得,兩個日誌恢復出來的數據不一致

所以,只有redo log是兩個狀態的情況——時刻A崩潰時,redo log數據恢復成還未提交到數據庫,所以可以把執行器的狀態變成c=1待提交狀態。binlog也沒有寫入,所以binlog恢復數據庫裏的數據c=0,所以成功恢復c=0未提交狀態,此時,因爲binlog沒有記錄,所以redo log未完成的事務可以被丟棄,保持c=0。時刻B崩潰時,redolog數據恢復,binlog已經寫入,則可以把數據恢復成c=1待提交狀態。綜上所述,redo log和binlog可以實現crash-safe。但是需要注意的是,通過數據恢復,不一定可以完全恢復數據。只可以恢復某個時間前的數據,不可以試圖將某個操作前後的數據進行合併(比如發生誤刪除操作後,想把誤刪除前的數據+誤刪除後還持續發生的業務數據),只能恢復誤刪除前的,誤刪除後的需要手工加進數據庫中

(還沒寫完……ing)

 

 

 

 

 

 

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started)) > 60

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章