政府網站內容建設方案怎么免費注冊域名
??? 書接上一篇文章,MySQL通過不同的策略來保證事務的ACID:原子性、一致性、隔離性、持久性,通過鎖機制實現(xiàn)隔離性,通過redo+undo+binlog三種日志實現(xiàn)事務的原子性、一致性和持久性。
??? 本文主要講MySQL的持久性的一個實現(xiàn)機制-兩階段提交策略。
?? 兩階段提交定義
?? 兩階段提交指的是MySQL在提交事務將臟數(shù)據刷盤的過程分為prepare和commit兩個階段,當客戶端commit命令開始執(zhí)行后,MySQL內部開啟一個XA(分布式事務)事務,并為該事務分配一個XID,先將redo log緩存中的數(shù)據刷新到日志,redo log刷盤后,redo log對該事務標記為prepare,磁盤的redo日志中也就存在該XID。接著,將binlog緩存中的數(shù)據刷盤,binlog刷盤完成后,磁盤的binlog中會存在該XID,會將該redo log上的事務標記為commit。至此,客戶端發(fā)起的commit命令執(zhí)行完成。
??? 那么問題來了,提交一個事務的時候直接寫到binlog中不行么,為啥非得先對redo log刷盤,然后再對binlog刷盤?
? 兩階段提交策略的作用
??? 這就引出了兩階段提交策略的作用:確保MySQL數(shù)據庫崩潰后重啟時能快速恢復。這個快速是建立在使用redo log恢復基礎上的,因為redo log的數(shù)據頁記錄的是物理頁的修改,并且大小和物理表空間中數(shù)據頁相同,利用redo log可以快速將未提交的事務提交并完成刷盤,因此提交事務時要使用兩階段提交策略。
??? 數(shù)據庫崩潰時兩階段提交的不同情況
??? 數(shù)據庫崩潰時,提交的事務(假設對表user中id=1 name="張三"的記錄執(zhí)行 update user set name="李四" where id = 1 )可能遇到如下
??? 1、redo log已經刷盤,事務被標記為prepare狀態(tài),binlog尚未刷盤,MySQL內部開啟的XA事務會給redo log標記唯一的事務號,binlog中不存在該事務號。
??? 2、redo log已經刷盤,事務被標記為prepare狀態(tài),binlog已經完成刷盤,MySQL內部開啟的XA事務會給redo log和binlog分別標記相同的事務號。
??? 3、redo log和binlog都已經完成刷盤,事務被標記為commit狀態(tài)。
??? 數(shù)據庫崩潰恢復時,會檢查redo log中的XA事務號是否在binlog中能找到。
??? 針對第1種情況,binlog中不存在redo log 中的XA事務號,則直接將事務回滾。
??? 針對第2種情況,binlog中找到了redo log中的XA事務號,但事務仍然是prepare狀態(tài),說明binlog將修改刷盤后還沒有來得及標記該事務為commit狀態(tài)數(shù)據庫就已經崩潰了,這個時候直接提交該事務即可。
????針對第3種情況,說明事務已經成功提交,崩潰恢復時事務無須處理。
??? 到這里兩階段提交策略就沒有問題了,但愛學習的小伙伴肯定就會問了,都說學以致用,那么理解兩階段提交策略原理到底有什么用呢?
??? 哈哈哈哈,這個問題我也在思考,除了裝逼之外,我暫時想不到其他在工作中能具體用到的地方,留作以后補充吧。
???