久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL事務(wù)的提交過(guò)程

共計(jì) 3420 個(gè)字符,預(yù)計(jì)需要花費(fèi) 9 分鐘才能閱讀完成。

本篇內(nèi)容介紹了“MySQL 事務(wù)的提交過(guò)程”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓丸趣 TV 小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

MySQL 事務(wù)提交過(guò)程
開(kāi)啟 binlog 后事務(wù)提交流程會(huì)變成兩階段提交,這里的兩階段提交并不涉及分布式事務(wù),當(dāng)然 mysql 把它稱之為內(nèi)部 xa 事務(wù)(Distributed Transactions),與之對(duì)應(yīng)的還有一個(gè)外部 xa 事務(wù)。

這里所謂的兩階段提交分別是 prepare 階段和 commit 階段。

內(nèi)部 xa 事務(wù)主要是 mysql 內(nèi)部為了保證 binlog 與 redo log 之間數(shù)據(jù)的一致性而存在的,這也是由其架構(gòu)決定的(binlog 在 mysql 層,而 redo log 在存儲(chǔ)引擎層);

外部 xa 事務(wù)則是指支持多實(shí)例分布式事務(wù),這個(gè)才算是真正的分布式事務(wù)。

既然是 xa 事務(wù),必然涉及到兩階段提交,對(duì)于內(nèi)部 xa 而言,同樣存在著提交的兩個(gè)階段。

下文會(huì)結(jié)合源碼詳細(xì)解讀內(nèi)部 xa 的兩階段提交過(guò)程,以及各種情況下,mysqld crash 后,mysql 如何恢復(fù)來(lái)保證事務(wù)的一致性。

數(shù)據(jù)庫(kù)版本:5.6.16

操作系統(tǒng)版本:CentOS 6.5

配置文件參數(shù):
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

不同的模式區(qū)別在于,寫文件調(diào)用 write 和落盤 fsync 調(diào)用的頻率不同,所導(dǎo)致的后果是 mysqld 或 os crash 后,不嚴(yán)格的設(shè)置可能會(huì)丟失事務(wù)的更新。

雙一模式是最嚴(yán)格的模式,這種設(shè)置情況下,單機(jī)在任何情況下不會(huì)丟失事務(wù)更新。】

測(cè)試條件:
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;

測(cè)試語(yǔ)句:
insert into user values(1, sanzhang , 張三

commit;

prepare 階段:

    1. 設(shè)置 undo state=TRX_UNDO_PREPARED;//trx_undo_set_state_at_prepare 調(diào)用

    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    // 設(shè)置 undo 段的標(biāo)記為 TRX_UNDO_PREPARED

                2. 設(shè)置事務(wù)狀態(tài)為 TRX_STATE_PREPARED

                3.trx_flush_log_if_needed  // 將產(chǎn)生的 redolog 刷入磁盤

            }

     }
     
     

commit 階段:

   1. 將事務(wù)產(chǎn)生的 binlog 寫入文件,刷入磁盤;

   2. 設(shè)置 undo 頁(yè)的狀態(tài), 置為 TRX_UNDO_TO_FREE 或 TRX_UNDO_TO_PURGE;  // trx_undo_set_state_at_finish 調(diào)用

   3. 記錄事務(wù)對(duì)應(yīng)的 binlog 偏移,寫入系統(tǒng)表空間; //trx_sys_update_mysql_binlog_offset 調(diào)用
   
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),設(shè)置 undo 狀態(tài)

                    trx_commit_in_memory(trx, lsn); // 釋放鎖資源,清理保存點(diǎn)列表,清理回滾段

                }        

        } 

    }
   
在任何情況下(機(jī)器掉電)mysqld crash 或者 os crash,MySQL 仍然能保證數(shù)據(jù)庫(kù)的一致性。數(shù)據(jù)的一致性是如何做到的哪?正是二階段提交。

我們結(jié)合幾種場(chǎng)景來(lái)分析下二階段提交是如何做到的:

1.prepare 階段,redo log 落盤前,mysqld crash

2.prepare 階段,redo log 落盤后,binlog 落盤前,mysqld crash

3.commit 階段,binlog 落盤后,mysqld crash

對(duì)于第一種情況,由于 redo 沒(méi)有落盤,毫無(wú)疑問(wèn),事務(wù)的更新肯定沒(méi)有寫入磁盤,數(shù)據(jù)庫(kù)的一致性受影響;

對(duì)于第二種情況,這時(shí)候 redo log 寫入完成,但 binlog 還未寫入,事務(wù)處于 TRX_STATE_PREPARED 狀態(tài),這是提交還是回滾呢?

對(duì)于第三種情況,此時(shí),redo log 和 binlog 都已經(jīng)落盤,只是 undo 狀態(tài)沒(méi)有更新,雖然 redo log 和 binlog 已經(jīng)一致了,事務(wù)是否應(yīng)該提交?

我們結(jié)合 mysqld 異常重啟后的執(zhí)行邏輯以及關(guān)鍵的源代碼。

對(duì)于第三種情況,我們可以搜集到未提交事務(wù)的 binlog event,所以需要提交;

對(duì)于第二種情況,由于 binlog 未寫入,需要通過(guò)執(zhí)行回滾操作來(lái)保證數(shù)據(jù)庫(kù)的一致性。

異常重啟后,如何判斷事務(wù)該提交還是回滾

1. 讀 binlog 日志,獲取崩潰時(shí)沒(méi)有提交的 event; //info- commit_list 中含有該元素

2. 若存在,則對(duì)應(yīng)的事務(wù)要提交;否則需要回滾。

判斷事務(wù)提交或回滾源碼如下:

上面討論了兩階段提交的基本流程,以及服務(wù)器異常 crash 后,mysql 如何重啟恢復(fù)保證 binlog 和數(shù)據(jù)的一致性。

簡(jiǎn)而言之,對(duì)于異常的 xa 事務(wù),若 binlog 已落盤,則事務(wù)應(yīng)該提交;binlog 未落盤,則事務(wù)就應(yīng)該回滾。

// 異常重啟后,回滾流程

innobase_rollback_by_xid
rollback_by_xid
trx_rollback_resurrected
 trx_rollback_active
 row_undo
 { // 從回滾頁(yè)獲取 undo 記錄  // 分析 undo 記錄類型  if (insert)
 row_undo_ins else row_undo_mod
 }

// 異常重啟后,提交流程

commit_by_xid
trx_commit_for_mysql

// 寫 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ā)數(shù)據(jù)變更的事件日志集合。

從庫(kù)請(qǐng)求主庫(kù)發(fā)送 binlog 并通過(guò)日志事件還原數(shù)據(jù)寫入從庫(kù),所以從庫(kù)的數(shù)據(jù)來(lái)源為 binlog。

這樣 MySQL 主庫(kù)只需做到 binlog 與本地?cái)?shù)據(jù)一致就可以保證主從庫(kù)數(shù)據(jù)一致(暫且忽略網(wǎng)絡(luò)傳輸引發(fā)的主從不一致)。

“MySQL 事務(wù)的提交過(guò)程”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-07-28發(fā)表,共計(jì)3420字。
轉(zhuǎn)載說(shuō)明:除特殊說(shuō)明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒(méi)有評(píng)論)
主站蜘蛛池模板: 万源市| 武邑县| 东辽县| 抚远县| 河西区| 宽城| 旬邑县| 清原| 太康县| 太湖县| 镇雄县| 郯城县| 芜湖市| 甘泉县| 微山县| 澳门| 莒南县| 太谷县| 永胜县| 泾川县| 荥阳市| 灵台县| 沁源县| 得荣县| 鄂托克旗| 新兴县| 乌审旗| 呼和浩特市| 武山县| 上饶市| 北海市| 麻城市| 鲁甸县| 双城市| 滦平县| 吐鲁番市| 九龙县| 洪雅县| 福清市| 临汾市| 濮阳县|