本篇內容介紹了“事務(wù)的提交過(guò)程”的有關(guān)知識,在實(shí)際案例的操作過(guò)程中,不少人都會(huì )遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學(xué)有所成!
MySQL事務(wù)提交過(guò)程
開(kāi)啟binlog后事務(wù)提交流程會(huì )變成兩階段提交,這里的兩階段提交并不涉及分布式事務(wù),當然mysql把它稱(chēng)之為內部xa事務(wù)(Distributed Transactions),與之對應的還有一個(gè)外部xa事務(wù)。
這里所謂的兩階段提交分別是prepare階段和commit階段。
內部xa事務(wù)主要是mysql內部為了保證binlog與redo log之間數據的一致性而存在的,這也是由其架構決定的(binlog在mysql層,而redo log 在存儲引擎層);
外部xa事務(wù)則是指支持多實(shí)例分布式事務(wù),這個(gè)才算是真正的分布式事務(wù)。
既然是xa事務(wù),必然涉及到兩階段提交,對于內部xa而言,同樣存在著(zhù)提交的兩個(gè)階段。
下文會(huì )結合源碼詳細解讀內部xa的兩階段提交過(guò)程,以及各種情況下,mysqld crash后,mysql如何恢復來(lái)保證事務(wù)的一致性。
數據庫版本:5.6.16
操作系統版本:CentOS 6.5
配置文件參數:
log-bin=/my/log/mysql-bin
binlog_format=ROW
set autocommit=0
innodb_support_xa=1
sync_binlog=1
innodb_flush_log_at_trx_commit=1
【innodb_flush_log_at_trx_commit=1,sync_binlog=1
不同的模式區別在于,寫(xiě)文件調用write和落盤(pán)fsync調用的頻率不同,所導致的后果是mysqld 或 os crash后,不嚴格的設置可能會(huì )丟失事務(wù)的更新。
雙一模式是最嚴格的模式,這種設置情況下,單機在任何情況下不會(huì )丟失事務(wù)更新?!?br/>
測試條件:
set autocommit=0;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(20) NOT NULL,
`account` varchar(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`) USING BTREE,
KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
測試語(yǔ)句:
insert into user values(1, 'sanzhang', '張三');
commit;
prepare階段:
1.設置undo state=TRX_UNDO_PREPARED; //trx_undo_set_state_at_prepare調用
2.刷事務(wù)更新產(chǎn)生的redo日志;【步驟1產(chǎn)生的redo日志也會(huì )刷入】
MYSQL_BIN_LOG::prepare
ha_prepare_low
{
engine:
binlog_prepare
innobase_xa_prepare
mysql:
trx_prepare_for_mysql
{
1.trx_undo_set_state_at_prepare //設置undo段的標記為T(mén)RX_UNDO_PREPARED
2.設置事務(wù)狀態(tài)為T(mén)RX_STATE_PREPARED
3.trx_flush_log_if_needed //將產(chǎn)生的redolog刷入磁盤(pán)
}
}
commit階段:
1.將事務(wù)產(chǎn)生的binlog寫(xiě)入文件,刷入磁盤(pán);
2.設置undo頁(yè)的狀態(tài),置為T(mén)RX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE; // trx_undo_set_state_at_finish調用
3.記錄事務(wù)對應的binlog偏移,寫(xiě)入系統表空間; //trx_sys_update_mysql_binlog_offset調用
MYSQL_BIN_LOG::commit
ordered_commit
{
1.FLUSH_STAGE
flush_cache_to_file // 刷binlog
2.SYNC_STAGE
sync_binlog_file //Call fsync() to sync the file to disk.
3.COMMIT_STAGE
ha_commit_low
{
binlog_commit
innobase_commit
trx_commit(trx)
{
trx_write_serialisation_history(trx, mtr); //更新binlog位點(diǎn),設置undo狀態(tài)
trx_commit_in_memory(trx, lsn); //釋放鎖資源,清理保存點(diǎn)列表,清理回滾段
}
}
}
在任何情況下(機器掉電)mysqld crash或者os crash,MySQL仍然能保證數據庫的一致性。數據的一致性是如何做到的哪?正是二階段提交。
我們結合幾種場(chǎng)景來(lái)分析下二階段提交是如何做到的:
1.prepare階段,redo log落盤(pán)前,mysqld crash
2.prepare階段,redo log落盤(pán)后,binlog落盤(pán)前,mysqld crash
3.commit階段,binlog落盤(pán)后,mysqld crash
對于第一種情況,由于redo沒(méi)有落盤(pán),毫無(wú)疑問(wèn),事務(wù)的更新肯定沒(méi)有寫(xiě)入磁盤(pán),數據庫的一致性受影響;
對于第二種情況,這時(shí)候redo log寫(xiě)入完成,但binlog還未寫(xiě)入,事務(wù)處于TRX_STATE_PREPARED狀態(tài),這是提交還是回滾呢?
對于第三種情況,此時(shí),redo log和binlog都已經(jīng)落盤(pán),只是undo狀態(tài)沒(méi)有更新,雖然redo log和binlog已經(jīng)一致了,事務(wù)是否應該提交?
我們結合mysqld異常重啟后的執行邏輯以及關(guān)鍵的源代碼。
對于第三種情況,我們可以搜集到未提交事務(wù)的binlog event,所以需要提交;
對于第二種情況,由于binlog未寫(xiě)入,需要通過(guò)執行回滾操作來(lái)保證數據庫的一致性。
異常重啟后,如何判斷事務(wù)該提交還是回滾
1.讀binlog日志,獲取崩潰時(shí)沒(méi)有提交的event; //info->commit_list中含有該元素
2.若存在,則對應的事務(wù)要提交;否則需要回滾。
判斷事務(wù)提交或回滾源碼如下:
上面討論了兩階段提交的基本流程,以及異常crash后,mysql如何重啟恢復保證binlog和數據的一致性。
簡(jiǎn)而言之,對于異常的xa事務(wù),若binlog已落盤(pán),則事務(wù)應該提交;binlog未落盤(pán),則事務(wù)就應該回滾。
//異常重啟后,回滾流程
innobase_rollback_by_xid rollback_by_xid trx_rollback_resurrected trx_rollback_active row_undo { //從回滾頁(yè)獲取undo記錄 //分析undo記錄類(lèi)型 if (insert) row_undo_ins else row_undo_mod }
//異常重啟后,提交流程
commit_by_xid trx_commit_for_mysql
//寫(xiě)binlog接口
handler.cc:binlog_log_row sql/binlog.cc:commit mysys/my_sync:my_sync sql/binlog.cc:sync_binlog_file handler/ha_innodb.cc:innobase_xa_prepare
binlog日志文件是為了解決MySQL主從復制功能而引入的一份新日志文件,它包含了引發(fā)數據變更的事件日志集合。
從庫請求主庫發(fā)送 binlog 并通過(guò)日志事件還原數據寫(xiě)入從庫,所以從庫的數據來(lái)源為 binlog。
這樣 MySQL 主庫只需做到 binlog 與本地數據一致就可以保證主從庫數據一致(暫且忽略網(wǎng)絡(luò )傳輸引發(fā)的主從不一致)。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站