MySQL 有哪些一致性日志
如果 MySQL 數(shù)據(jù)庫斷電了燎字,未提交的事務(wù)怎么辦焕阿?
依靠日志
MySQL InnoDB 引擎中和一致性相關(guān)的有:重做日志(redo log)邢羔、回滾日志(undo log)鸦采、二進制日志(binlog)
- redo 日志:每當(dāng)有操作執(zhí)行前弧腥,在數(shù)據(jù)真正更改前,會先把相關(guān)操作寫入 redo 日志赏酥。
當(dāng)斷電喳整,或發(fā)生一些意外,導(dǎo)致后續(xù)任務(wù)無法完成時裸扶,待系統(tǒng)恢復(fù)后框都,可以繼續(xù)完成這些更改 - undo 日志:也叫撤銷日志,記錄事務(wù)開始前數(shù)據(jù)的狀態(tài)呵晨,當(dāng)一些更改在執(zhí)行一半時
發(fā)生意外而無法完成魏保,可以根據(jù)撤銷日志恢復(fù)到更改之前的狀態(tài)
舉例:事務(wù) T1 更新數(shù)據(jù) X ,對 X 執(zhí)行 Update 操作摸屠,從 10 更新到 20 對應(yīng)的 Redo 日志為<T1谓罗,X,20> Undo 日志為 <T1季二,X檩咱,10> - binlog 日志是 MySQL server 層維護的一種二進制日志,是 MySQL 最重要的日志之一
它記錄了所有的DDL 和 DML 語句胯舷,除了數(shù)據(jù)查詢語句 select刻蚯, show 等,還包含語句所執(zhí)行的消耗的時間
binlog 的主要目的是復(fù)制和恢復(fù)
用來記錄對 MySQL 數(shù)據(jù)更新或潛在發(fā)生更新的 SQL 語句桑嘶,并以事務(wù)日志的形式保存在磁盤中
binlog 主要應(yīng)用在 MySQL 的主從復(fù)制過程中炊汹,MySQL 集群在 Master 端開啟 binlog
Master 把它的二進制日志傳遞給 slaves 節(jié)點
再從節(jié)點回放來達到 master-slave 數(shù)據(jù)保存一致
# 查看 binlog 文件內(nèi)容
show binlog events;
# 查看指定 binlog 文件的內(nèi)容
show binlog events in 'MySQL-bin.000001';
# 查看正在寫入的binlog 文件
show master status \G;
# 獲取 binlog 文件列表
show binary logs;
XA 規(guī)范是如何定義的
事務(wù)協(xié)調(diào)者(Transaction Manager)
XA 事務(wù)是基于兩階段提交協(xié)議的
需要有一個協(xié)調(diào)者,來保證所有的事務(wù)參與者完成了準(zhǔn)備工作逃顶,也就是 2PC 的第一階段
如果事務(wù)協(xié)調(diào)者收到所有參與者都準(zhǔn)備好的消息
會通知所有的事務(wù)都可以提交讨便,也就是 2PC 的第二階段
在分布式系統(tǒng)中,兩臺機器理論上無法達到一致的狀態(tài)以政,需要引入一個單點進行協(xié)調(diào)
協(xié)調(diào)者捐寥,也就是 事務(wù)管理器控制著全局事務(wù)泞辐,管理事務(wù)生命周期,并協(xié)調(diào)資源
資源管理器(Resource Manager)
負責(zé)控制和管理實際資源,比如數(shù)據(jù)庫或 JMS 隊列
目前膊畴,主流數(shù)據(jù)庫都是提供了對 XA 的支持
在 JMS 規(guī)范中办陷,即 Java 消息服務(wù)(Java Message Service) 中
也基于 XA 定義了對事務(wù)的支持
XA 事務(wù)的執(zhí)行流程
根據(jù) 2PC 的規(guī)范私蕾,XA 將一次事務(wù)分割成了兩個階段猎提,即 Prepare 和 Commit 階段
- Prepare 階段,TM 向所有 RM 發(fā)送 prepare 指令寸五,RM 接受到指令后
執(zhí)行數(shù)據(jù)修改和日志記錄等操作梳凛,然后返回可以提交或者不提交的消息給 TM
如果事務(wù)協(xié)調(diào)者 TM 收到所有參與者都準(zhǔn)備好的消息,會通知所有的事務(wù)提交梳杏,然后進入第二階段 - Commit 階段韧拒,TM 接受到所有 RM 的 prepare 結(jié)果
如果所有 RM 返回是不可提交或者超時淹接,那么向所有 RM 發(fā)送 Rollback 命令
如果所有 RM 都返回可以提交,那么向所有 RM 發(fā)送 Commit 命令叛溢,完成一次事務(wù)操作
MySQL 如何實現(xiàn) XA 規(guī)范
MySQL 中 XA 事務(wù)有兩種情況塑悼,內(nèi)部 XA 和 外部 XA
其區(qū)別是事務(wù)發(fā)生在 MySQL 服務(wù)器單機上,還是發(fā)生在多個外部節(jié)點間上
內(nèi)部 XA
在 MySQL 的 InnoDB 存儲引擎中楷掉,開啟 binlog 的情況下
MySQL 會同時維護 binlog 日志和 InnoDB 的 redo log厢蒜,為了保證這兩個日志的一致性
MySQL 使用了 XA 事務(wù),由于有在 MySQL 單機上工作烹植,所以被稱為內(nèi)部 XA
內(nèi)部 XA 事務(wù)由 binlog 作為協(xié)調(diào)者斑鸦,在事務(wù)提交時,則需要將提交信息寫入二進制日志
binlog 的參與者是 MySQL 本身
外部XA
外部 XA 是典型的分布式事務(wù)草雕,MySQL 支持 XA START/END/PREPARE/Commit 這些SQL語句
MySQL 外部 XA 主要應(yīng)用在數(shù)據(jù)庫代理層巷屿,實現(xiàn)對 MySQL 數(shù)據(jù)庫的分布式事務(wù)支持
例如:開源的數(shù)據(jù)庫中間層,比如淘寶的 TDDL墩虹,阿里巴巴 B2B 的 Cobar 等
外部 XA 一般是針對跨多 MySQL 實例的分布式事務(wù)嘱巾,需要應(yīng)用層作為協(xié)調(diào)者
比如寫業(yè)務(wù)代碼,在代碼中決定提交還是回滾诫钓,并且在崩潰時進行恢復(fù)
Binlog 中的 Xid
binlog 有多種數(shù)據(jù)類型
- statement 格式浓冒,記錄為基本語句,包含 Commit
- row 格式尖坤,記錄為基于行
- mixed 格式,日志記錄使用混合格式
binlog 會添加一個 XID_EVENT 作為事務(wù)的結(jié)束闲擦,該事件記錄了事務(wù)的 ID 也就是 Xid
在 MySQL 進行崩潰恢復(fù)時根據(jù) binlog 中提交的情況來決定如何恢復(fù)
Binlog 同步過程
當(dāng)有事務(wù)提交時:
- 第一步慢味,InnoDB 進入 Prepare 階段,并且 write / sync redo log墅冷,寫 redo log
將事務(wù)的 XID 寫入到 redo 日志中纯路,binlog 不作任何操作 - 第二步,進行 write / sync Binlog寞忿,寫 binlog 日志驰唬,也會把 XID 寫入到 Binlog
- 第三步,調(diào)傭 InnoDB 引擎的 Commit 完成事務(wù)的提交腔彰,將 Commit 信息寫入到 redo 日志中
如果是在 第一步和 第二步失敗叫编,則整個事務(wù)回滾
如果是在第三步失敗,則 MySQL 在重啟后會檢查 XID 是否已經(jīng)提交
若沒有提交霹抛,事務(wù)需要重新執(zhí)行搓逾,就會在存儲引擎中再執(zhí)行一次提交操作
保障 redo log 和 binlog 數(shù)據(jù)的一致性,防止數(shù)據(jù)丟失
在實際執(zhí)行中杯拐,牽扯到操作系統(tǒng)緩存 Buffer 何時同步到文件系統(tǒng)中
MySQL 支持用戶自定義在 Commit 時如何將 log buffer 中的日志刷到 log file 中
通過變量 innodb_flush_log_at_trx_Commit 的值來決定
在 log buffer 中內(nèi)容稱為臟日志