MySql事務(wù)處理_第1頁(yè)
MySql事務(wù)處理_第2頁(yè)
MySql事務(wù)處理_第3頁(yè)
MySql事務(wù)處理_第4頁(yè)
MySql事務(wù)處理_第5頁(yè)
已閱讀5頁(yè),還剩13頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、什么是事務(wù)事務(wù)就是一段sql 語(yǔ)句的批處理,但是這個(gè)批處理是一個(gè)atom(原子),不可分割,要么都執(zhí)行,要么回滾(rollback)都不執(zhí)行。(保證數(shù)據(jù)操作的安全性)為什么出現(xiàn)這種技術(shù)為什么要使用事務(wù)這個(gè)技術(shù)呢? 現(xiàn)在的很多軟件都是多用戶(hù),多程序,多線程的,對(duì)同一個(gè)表可能同時(shí)有很多人在用,為保持?jǐn)?shù)據(jù)的一致性,所以提出了事務(wù)的概念。這樣很抽象,舉個(gè)例子-口述。如何使用事務(wù)(1)只有InnoDB /BDB的之類(lèi)的transaction_safe table(commit-or-rollback,如果是安全的) 才能支持。默認(rèn)的engine 

2、;MyISAM 是不支持事務(wù)的。建立InnoDB 表:Create table . type=InnoDB;  Alter table table_name type=InnoDB;(如何查看已有表的類(lèi)型: show create table table_name)這樣我們就可以在InnoDB 表上進(jìn)行事務(wù)操作了!(2)啟動(dòng)事務(wù)的方法-2種:1、(推薦)begin ,rollback,commit .當(dāng)然有的人用begin /

3、begin work .推薦用START TRANSACTION 是SQL-99標(biāo)準(zhǔn)啟動(dòng)一個(gè)事務(wù)。    start transaction;update from account set money=money-100 where name='a'update from account set money=money+100 where name='b'

4、commit;解釋?zhuān)?#160;這樣start transaction 手動(dòng)開(kāi)啟事務(wù),commit 手動(dòng)關(guān)閉事務(wù)。2、默認(rèn)的時(shí)候autocommit=1 自動(dòng)提交是開(kāi)啟的,所以你可以理解為每條語(yǔ)句一輸入到mysql就commit 了。當(dāng)你 set autocommit=0 時(shí)候,你可以這樣:update from account set money=money-100 where name='a'update from 

5、account set money=money+100 where name='b'commit;/ 默認(rèn)都不提交,只有手動(dòng)鍵入commit 時(shí)候才上述都提交。但注意當(dāng)你用 set autocommit=0 的時(shí)候,你以后所有的SQL都將做為事務(wù)處理,直到你用commit確認(rèn)或rollback結(jié)束,注意當(dāng)你結(jié)束這個(gè)事務(wù)的同時(shí)也開(kāi)啟了個(gè)新的事務(wù)事務(wù)是必須滿(mǎn)足4個(gè)條件(ACID)      原子性(Autmic):事務(wù)在執(zhí)行性,要做到“要么不做,要么全做!”,就是說(shuō)不允許事

6、務(wù)部分得執(zhí)行。即使因?yàn)楣收隙故聞?wù)不能完成,在rollback時(shí)也要消除對(duì)數(shù)據(jù)庫(kù)得影響!     一致性(Consistency):事務(wù)得操作應(yīng)該使使數(shù)據(jù)庫(kù)從一個(gè)一致?tīng)顟B(tài)轉(zhuǎn)變倒另一個(gè)一致得狀態(tài)!     隔離性(Isolation):如果多個(gè)事務(wù)并發(fā)執(zhí)行,應(yīng)象各個(gè)事務(wù)獨(dú)立執(zhí)行一樣!持久性(Durability):一個(gè)成功執(zhí)行得事務(wù)對(duì)數(shù)據(jù)庫(kù)得作用是持久得,即使數(shù)據(jù)庫(kù)應(yīng)故障出錯(cuò),也應(yīng)該能夠恢復(fù)!不加控制的并發(fā)存取會(huì)產(chǎn)生以下幾種錯(cuò)誤1 丟失修改(lost updates) 當(dāng)多個(gè)事務(wù)并發(fā)修改一個(gè)數(shù)據(jù)時(shí),不加控制

7、會(huì)得出錯(cuò)誤的結(jié)果,一個(gè)修改會(huì)覆蓋掉另一個(gè)修改。 2 讀的不可重復(fù)性 當(dāng)多個(gè)事務(wù)按某種時(shí)間順序存取若干數(shù)據(jù)時(shí),如果對(duì)并發(fā)存取不加控制,也會(huì)產(chǎn)生錯(cuò)誤。 3 臟讀(DIRDY DATA),讀的不一致性 4 光標(biāo)帶來(lái)的當(dāng)前值的混亂 事務(wù)在執(zhí)行過(guò)程中它在某個(gè)表上的當(dāng)前查找位置是由光標(biāo)表示的。光標(biāo)指向當(dāng)前正處理的記錄。當(dāng)處理完該條記錄后,則指向下一條記錄。在多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),某一事務(wù)的修改可能產(chǎn)生負(fù)作用,使與這些光標(biāo)有關(guān)的事務(wù)出錯(cuò)。 5 未釋放修改造成連鎖退出 一個(gè)事務(wù)在進(jìn)行修改操作的過(guò)程中可能會(huì)發(fā)生故障,這時(shí)需要將已做的修改回退(R

8、ollback)。如果在已進(jìn)行過(guò)或已發(fā)現(xiàn)錯(cuò)誤尚未復(fù)原之前允許其它事務(wù)讀已做過(guò)修改(臟讀),則會(huì)導(dǎo)致連鎖退出。 6 一事務(wù)在對(duì)一表更新時(shí),另外的事務(wù)卻修改或刪除此表的 定義。 數(shù)據(jù)庫(kù)會(huì)為每個(gè)事務(wù)自動(dòng)地設(shè)置適當(dāng)級(jí)別的鎖定。對(duì)于前面講述的問(wèn)題:臟讀、未釋放修改造成的連鎖退出、一事務(wù)在對(duì)一表更新時(shí)另外的事務(wù)卻修改或刪除此表的定義,數(shù)據(jù)庫(kù)都會(huì)自動(dòng)解決。而另外的三個(gè)問(wèn)題則需要在編程過(guò)程中人為地定義事務(wù)或加鎖來(lái)解決。 事務(wù)處理的機(jī)制簡(jiǎn)單地說(shuō)就是留下更新日志。數(shù)據(jù)庫(kù)會(huì)根據(jù)這些日志信息,在必要時(shí)將舊數(shù)據(jù)取回,或者在發(fā)生錯(cuò)誤時(shí)將數(shù)據(jù)恢復(fù)到原先的狀態(tài)。事務(wù)處理日志文件:UND

9、O log日志UNDO日志又被稱(chēng)為回滾段(Rollback Segment),在進(jìn)行數(shù)據(jù)的捕入、更新、刪除的場(chǎng)合,保存變更前的數(shù)據(jù),在表的內(nèi)容保存了指向UNDO日志的指針,ROLLBACK時(shí)根據(jù)這個(gè)指針米獲得舊數(shù)據(jù),并覆蓋新數(shù)據(jù)。ROLLBACK后,或者COMMIT后UNDO日志將被刪除。另外,UNDO日志也使用于保持?jǐn)?shù)據(jù)讀取的整合性。例如,在用戶(hù)A對(duì)數(shù)據(jù)進(jìn)行了更新,但還沒(méi)有提交時(shí),用戶(hù)B要參照數(shù)據(jù)怎么辦呢?此時(shí)讓用戶(hù)B看到更新后的數(shù)據(jù)顯然是不行的,其實(shí)是通過(guò)保存的指針讓UNDO日志中的數(shù)據(jù)呈現(xiàn)給用戶(hù)B的。REDO log日志REDO日志根據(jù)數(shù)據(jù)庫(kù)的不同,有時(shí)被稱(chēng)為事務(wù)處理日志或日志.事務(wù)處理

10、確定后,由于錯(cuò)誤等原因使數(shù)據(jù)的更新沒(méi)有正確反映到數(shù)據(jù)庫(kù)中的時(shí)候,REDO日志提供了數(shù)據(jù)恢復(fù)用的孚段.僅僅看上述的說(shuō)明可能還不能理解。那到底事務(wù)處理確定后,數(shù)據(jù)的更新沒(méi)有反映到數(shù)據(jù)庫(kù)中這種狀態(tài)是在什么時(shí)候發(fā)生的呢?這個(gè)必須首先說(shuō)明。我們通常提到"更新(或變更)"就一句話帶過(guò),其實(shí)在數(shù)據(jù)庫(kù)內(nèi)部是需要經(jīng)過(guò)較復(fù)雜的處理的過(guò)程的,一般在數(shù)據(jù)庫(kù)中進(jìn)行更新處理時(shí),并非立即更新數(shù)據(jù)文件,而是首先在被稱(chēng)緩沖(buffer cash)的內(nèi)存空間中進(jìn)行數(shù)據(jù)更新,并將這些保存到REDO日志文件中。到現(xiàn)在為止太家會(huì)以為所有的處理都是實(shí)時(shí)的,其實(shí)在數(shù)據(jù)庫(kù)中向數(shù)據(jù)文件寫(xiě)入時(shí)是有延遲(或稱(chēng)為滯后)的。向數(shù)

11、據(jù)文件的寫(xiě)入動(dòng)作是在觸發(fā)稱(chēng)為檢查點(diǎn)( check point) 時(shí)非同步進(jìn)行的。檢查點(diǎn)撥一定的周期觸發(fā)。如果頻繁進(jìn)行這樣復(fù)雜的處理的話,尤其是對(duì)硬盤(pán)進(jìn)行寫(xiě)入處理時(shí)將會(huì)出現(xiàn)很高的負(fù)荷。因此現(xiàn)在的處理方式是,數(shù)據(jù)庫(kù)將對(duì)硬盤(pán)的寫(xiě)入操作稍微保留片刻, 當(dāng)檢查點(diǎn)(check point)到來(lái)時(shí)再集中處理,這樣就會(huì)顯著減少訪問(wèn)硬盤(pán)的次數(shù),性能得到改善。問(wèn)題出現(xiàn)在REDO日志的更新與數(shù)據(jù)文件的更新之間的延遲上。大家想象一下, 如果在這個(gè)延遲的當(dāng)口發(fā)生了停電,硬件錯(cuò)誤時(shí)會(huì)出現(xiàn)什么悄況呢?很顯然,內(nèi)存中的信息將會(huì)消失,只剩下在REDO日志中保存的信息了。REDO日志正是用于復(fù)原的.數(shù)據(jù)庫(kù)在錯(cuò)誤排除后的第一次起動(dòng)

12、時(shí)進(jìn)行稱(chēng)為Roll forward的處理,Roll forward處理具體做法是,從REDO日志中抽出從最后的檢查點(diǎn)到錯(cuò)誤發(fā)生時(shí)間點(diǎn)間的事務(wù)處理,然后重新執(zhí)行一次(REDO)。這樣,數(shù)據(jù)庫(kù)就恢復(fù)到錯(cuò)誤發(fā)生前的狀態(tài)了。Redo log undo log區(qū)別redo->記錄所有操作,用于恢復(fù)undo->記錄所有的前印象,用于回滾redo->已遞交的事務(wù),實(shí)例恢復(fù)時(shí)要寫(xiě)到數(shù)據(jù)文件去的undo->未遞交的事務(wù).redo的原因是:每次commit時(shí),將數(shù)據(jù)的修改立即寫(xiě)到redo中,但是并不一定同時(shí)將該數(shù)據(jù)的修改寫(xiě)到數(shù)據(jù)文件中。undo的原因是:口述。undo 也是也是datafi

13、le, 可能dirty buffer 沒(méi)有寫(xiě)回到磁盤(pán)里面去。只有先redo apply 成功了,才能保證undo datafile 里面的東西都是正確的,然后才能rollback做undo的目的是使系統(tǒng)恢復(fù)到系統(tǒng)崩潰前(關(guān)機(jī)前)的狀態(tài),再進(jìn)行redo是保證系統(tǒng)的一致性.不做undo,系統(tǒng)就不會(huì)知道之前的狀態(tài),redo就無(wú)從談起undo log原理使用undo log時(shí),要求:1. 記錄修改日志時(shí)(redo log),(T,x,v)中v為x修改前的值,這樣才能借助這條日志來(lái)回滾;2. 事務(wù)提交后,必須在事務(wù)的所有修改(包括記錄的修改日志)都持久化后才能寫(xiě)COMMIT T日志;這樣才能保證,宕機(jī)恢

14、復(fù)時(shí),已經(jīng)COMMIT的事務(wù)的所有修改都已經(jīng)持久化,不需要回滾。 使用undo log時(shí)事務(wù)執(zhí)行順序1. 記錄START T 2. 記錄需要修改的記錄的舊值(要求持久化)3. 根據(jù)事務(wù)的需要更新數(shù)據(jù)庫(kù)(要求持久化)4. 記錄COMMIT T 使用undo log進(jìn)行宕機(jī)回滾1. 掃描日志,找出所有已經(jīng)START,還沒(méi)有COMMIT的事務(wù)。2. 針對(duì)所有未COMMIT的日志,根據(jù)redo log來(lái)進(jìn)行回滾。 如果數(shù)據(jù)庫(kù)訪問(wèn)很多,日志量也會(huì)很大,宕機(jī)恢復(fù)時(shí),回滾的工作量也就很大,為了加快回滾,可以通過(guò)checkpoint機(jī)制來(lái)加速回滾,在日志中記錄checkpoint_start (T1,T2Tn

15、) (Tx代表做checkpoint時(shí),正在進(jìn)行還未COMMIT的事務(wù))等待所有正在進(jìn)行的事務(wù)(T1Tn)COMMIT在日志中記錄checkpoint_end借助checkpoint來(lái)進(jìn)行回滾從后往前,掃描undo log1,如果先遇到checkpoint_start, 則將checkpoint_start之后的所有未提交的事務(wù)進(jìn)行回滾;2. 如果先遇到checkpoint_end, 則將前一個(gè)checkpoint_start之后所有未提交的事務(wù)進(jìn)行回滾;(在checkpoint的過(guò)程中,可能有很多新的事務(wù)START或者COMMIT)。 使用undo log,在寫(xiě)COMMIT日志時(shí),要求red

16、o log以及事務(wù)的所有修改都必須已經(jīng)持久化,這種做法通常很影響性能。redo log原理redo log是指在回放日志的時(shí)候把已經(jīng)COMMIT的事務(wù)重做一遍,對(duì)于沒(méi)有commit的事務(wù)按照abort處理,不進(jìn)行任何操作。使用redo log時(shí),要求:1. 記錄redo log時(shí),(T,x,v)中的v必須是x修改后的值,否則不能通過(guò)redo log來(lái)恢復(fù)已經(jīng)COMMIT的事務(wù)。2. 寫(xiě)COMMIT T日志之前,事務(wù)的修改不能進(jìn)行持久化,否則恢復(fù)時(shí),對(duì)于未COMMIT的操作,可能有數(shù)據(jù)已經(jīng)修改,但重放redo log不會(huì)對(duì)該事務(wù)做任何處理,從而不能保證事務(wù)的原子性。 使用redo log時(shí)事務(wù)執(zhí)

17、行順序1. 記錄START T2. 記錄事務(wù)需要修改記錄的新值(要求持久化)3. 記錄COMMIT T(要求持久化)4. 將事務(wù)相關(guān)的修改寫(xiě)入數(shù)據(jù)庫(kù) 使用redo log重做事務(wù)1. 掃描日志,找到所有已經(jīng)COMMIT的事務(wù);2. 對(duì)于已經(jīng)COMMIT的事務(wù),根據(jù)redo log重做事務(wù); 在日志中使用checkpoint1. 在日志中記錄checkpoint_start (T1,T2.Tn) (Tx代表做checkpoint時(shí),正在進(jìn)行還未COMMIT的日志)2. 將所有已提交的事務(wù)的更改進(jìn)行持久化;3. 在日志中記錄checkpoint_end 根據(jù)checkpoint來(lái)加速恢復(fù)從后往前,

18、掃描redo log1,如果先遇到checkpoint_start, 則把T1Tn以及checkpoint_start之后的所有已經(jīng)COMMIT的事務(wù)進(jìn)行重做;2. 如果先遇到checkpoint_end, 則T1Tn以及前一個(gè)checkpoint_start之后所有已經(jīng)COMMIT的事務(wù)進(jìn)行重做; 與undo log類(lèi)似,在使用時(shí)對(duì)持久化以及事務(wù)操作順序的要求都比較高,可以將兩者結(jié)合起來(lái)使用,在恢復(fù)時(shí),對(duì)于已經(jīng)COMMIT的事務(wù)使用redo log進(jìn)行重做,對(duì)于沒(méi)有COMMIT的事務(wù),使用undo log進(jìn)行回滾。redo/undo log結(jié)合起來(lái)使用時(shí),要求同時(shí)記錄操作修改前和修改后的值,

19、如(T,x,v,w),v為x修改前的值,w為x修改后的值,具體操作順序?yàn)椋?. 記錄START T2. 記錄修改日志(T,x,v,w)(要求持久化,其中v用于undo,w用于redo)3. 更新數(shù)據(jù)庫(kù)4. 記錄 COMMIT T 4和3的操作順序沒(méi)有嚴(yán)格要求,并且都不要求持久化;因?yàn)槿绻礄C(jī)時(shí)4已經(jīng)持久化,則恢復(fù)時(shí)可通過(guò)redo log來(lái)重做;如果宕機(jī)時(shí)4未持久化,則恢復(fù)時(shí)可通過(guò)undo log來(lái)回滾;在處理checkpoint時(shí),可采用與redo log相同的處理方式。什么是binlogbinlog日志用于記錄所有更新且提交了數(shù)據(jù)或者已經(jīng)潛在更新提交了數(shù)據(jù)(例如,沒(méi)有匹配任何行的一個(gè)DELE

20、TE)的所有語(yǔ)句。語(yǔ)句以“事件”的形式保存,它描述數(shù)據(jù)更改。binlog作用1.恢復(fù)使能夠最大可能地更新數(shù)據(jù)庫(kù),因?yàn)槎M(jìn)制日志包含備份后進(jìn)行的所有更新。2.在主復(fù)制服務(wù)器上記錄所有將發(fā)送給從服務(wù)器的語(yǔ)句。 binlog未打卡狀態(tài)下的提交流程測(cè)試前置條件:set autocommit=0;create table tt(col1 int, col2 varchar(100); 測(cè)試語(yǔ)句:insert into tt values(1, 'abcdef');commit;     無(wú)論對(duì)于dml語(yǔ)句【insert,update,delete等

21、】還是dcl語(yǔ)句【commit,rollback】,mysql提供了公共接口mysql_execute_command,我們先分析mysql_execute_command接口的基本流程:<span style="font-size: 14px;">mysql_execute_command   switch (command)          case SQLCOM_INSERT:  

22、60;             mysql_insert();                break;         case SQLCOM_UPDATE:    

23、            mysql_update();                break;         case SQLCOM_DELETE:     

24、60;          mysql_delete();                break;       .           if thd->

25、is_error()  /語(yǔ)句執(zhí)行錯(cuò)誤     trans_rollback_stmt(thd);  else    trans_commit_stmt(thd); </span>可以看到執(zhí)行任何語(yǔ)句最后,都會(huì)執(zhí)行trans_rollback_stmt,或trans_commit_stmt,這兩個(gè)調(diào)用分別是語(yǔ)句級(jí)提交和語(yǔ)句級(jí)回滾。語(yǔ)句級(jí)提交,對(duì)于非自動(dòng)模式提交情況下,主要作兩件事情,一是釋放autoinc鎖(什么是他-口述),這個(gè)鎖主要用來(lái)處理多個(gè)事務(wù)互斥地獲取自

26、增列值,因此,無(wú)論最后該語(yǔ)句提交或是回滾,該資源都是需要而且可以立馬放掉的。二是標(biāo)識(shí)語(yǔ)句在事務(wù)中位置,方便語(yǔ)句級(jí)回滾。執(zhí)行commit后,可以進(jìn)入commit流程,現(xiàn)在來(lái)看看具體事務(wù)提交的流程是怎樣的。<span style="font-size: 14px;">mysql_execute_command    trans_commitha_commit_trans(thd, FALSE);    TC_LOG_DUMMY:ha_commit_low   

27、;     ha_commit_low()                innobase_commit                        

28、0;   /獲取innodb層對(duì)應(yīng)的事務(wù)結(jié)構(gòu)                trx = check_trx_exists(thd);                 if(單個(gè)語(yǔ)句,且非自動(dòng)提交)   

29、0;                                 /釋放自增列占用的autoinc鎖資源             

30、60;       lock_unlock_table_autoinc(trx);                     /標(biāo)識(shí)sql語(yǔ)句在事務(wù)中的位置,方便語(yǔ)句級(jí)回滾            

31、60;        trx_mark_sql_stat_end(trx);                                else 事務(wù)提交  

32、0;                                  innobase_commit_low()            &

33、#160;                                   trx_commit_for_mysql();            

34、                 <span style="color: #ff0000;">trx_commit</span>(trx);                     &#

35、160;  /確定事務(wù)對(duì)應(yīng)的redo日志是否落盤(pán)【根據(jù)flush_log_at_trx_commit參數(shù),確定redo日志落盤(pán)方式】                     trx_commit_complete_for_mysql(trx);trx_flush_log_if_needed_low(trx->commit_lsn);log_write_up_to

36、(lsn);                             </span><br><br>trx_commit    trx_commit_low         

37、           trx_write_serialisation_history                            trx_undo_update_cleanup /供purge線程處理,清理回滾頁(yè)      

38、60;                 trx_commit_in_memory                            lock_trx_release_locks /釋放鎖資源

39、60;               trx_flush_log_if_needed(lsn) /刷日志                trx_roll_savepoints_free /釋放savepoints             &#

40、160;            mysql通過(guò)WAL方式,來(lái)保證數(shù)據(jù)庫(kù)事務(wù)的一致性和持久性,即ACID特性中的C(consistent)和D(durability)。WAL(Write-Ahead Logging)是一種實(shí)現(xiàn)事務(wù)日志的標(biāo)準(zhǔn)方法,具體而言就是修改記錄前,一定要先寫(xiě)日志;事務(wù)提交過(guò)程中,一定要保證日志先落盤(pán),才能算事務(wù)提交完成。通過(guò)WAL方式,在保證事務(wù)特性的情況下,可以提交數(shù)據(jù)庫(kù)的性能。從上述流程可以看出,提交過(guò)程中,主要做了4件事情,首先是清理undo段信息,對(duì)于innodb存儲(chǔ)

41、引擎的更新操作來(lái)說(shuō),undo段需要purge,這里的purge主要職能是,真正刪除物理記錄。在執(zhí)行delete或update操作時(shí),實(shí)際舊記錄沒(méi)有真正刪除,只是在記錄上打了一個(gè)標(biāo)記,而是在事務(wù)提交后,purge線程真正刪除,釋放物理頁(yè)空間。因此,提交過(guò)程中會(huì)將undo信息加入purge列表,供purge線程處理。然后是釋放鎖資源,mysql通過(guò)鎖互斥機(jī)制保證不同事務(wù)不同時(shí)操作一條記錄,事務(wù)執(zhí)行后才會(huì)真正釋放所有鎖資源,并喚醒等待其鎖資源的其他事務(wù);再就是刷redo日志,前面我提到了,mysql實(shí)現(xiàn)事務(wù)一致性和持久性的機(jī)制。通過(guò)redo日志落盤(pán)操作,保證了即使修改的數(shù)據(jù)頁(yè)沒(méi)有即使更新到磁盤(pán),只要

42、日志是完成了,就能保證數(shù)據(jù)庫(kù)的完整性和一致性;最后就是清理保存點(diǎn)列表,每個(gè)語(yǔ)句實(shí)際都會(huì)有一個(gè)savepoint(保存點(diǎn)),保存點(diǎn)作用是為了可以回滾到事務(wù)的任何一個(gè)語(yǔ)句執(zhí)行前的狀態(tài),由于事務(wù)都已經(jīng)提交了,所以保存點(diǎn)列表可以被清理了。     關(guān)于里面提到的mysql的鎖機(jī)制,purge原理,redo日志,undo段等內(nèi)容,以后再說(shuō)。<span style="font-size: 14px;">struct trx_t         t

43、rx_rseg_t* rseg;       /*!< rollback segment assigned to the                    transaction, or NULL if not assigned        

44、60;trx_undo_t* insert_undo;    /*!< pointer to the insert undo log, or                    NULL if no inserts performed yet */    trx_undo_t* update_undo; 

45、60;  /*!< pointer to the update undo log, or                    NULL if no update performed yet */    const char* mysql_log_;       

46、             /*!< if MySQL binlog is used, this field                    contains a pointer to the latest file   

47、0;                name; this is NULL if binlog is not                    used */    ib_int64_t 

48、 mysql_log_offset;                    /*!< if MySQL binlog is used, this                    field

49、 contains the end offset of the                    binlog entry */  /* The rollback segment memory object */struct trx_rseg_t    /* Fields for update undo logs */

50、60;   UT_LIST_BASE_NODE_T(trx_undo_t) update_undo_list;                    /* List of update undo logs */    UT_LIST_BASE_NODE_T(trx_undo_t) update_undo_cached; 

51、;                   /* List of update undo log segments                    cached for fast reuse */ 

52、   /*-*/    /* Fields for insert undo logs */    UT_LIST_BASE_NODE_T(trx_undo_t) insert_undo_list;                    /* List of insert undo logs

53、 */    UT_LIST_BASE_NODE_T(trx_undo_t) insert_undo_cached;                    /* List of insert undo log segments           &

54、#160;        cached for fast reuse */</span>binlog打開(kāi)狀態(tài)下的提交流程開(kāi)啟binlog后事務(wù)提交流程會(huì)變成兩階段提交,這里的兩階段提交并不涉及分布式事務(wù),當(dāng)然mysql把它稱(chēng)之為內(nèi)部xa事務(wù)(Distributed Transactions),與之對(duì)應(yīng)的還有一個(gè)外部xa事務(wù)。內(nèi)部xa事務(wù)我理解主要是mysql內(nèi)部為了保證binlog與redo log之間數(shù)據(jù)的一致性而存在的,這也是由其架構(gòu)決定的(binlog在mysql層,而redo log 在存儲(chǔ)引擎

55、層);而外部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ù)的一致性。測(cè)試環(huán)境:OS:windowsDB:mysql 5.6.12engine:innodb 配置文件參數(shù):log-bin=D:chuckmysqllog5-6-12mysql-binbinlog_format=ROWset autocommit=0;sync_binlog=1;innodb_flush_l

56、og_at_trx_commit=1;innodb_support_xa=1; 測(cè)試前置條件:create table tt(col1 int, col2 varchar(100); 測(cè)試語(yǔ)句:insert into tt values(1, 'abcdef');commit;      打開(kāi)binlog選項(xiàng)后,執(zhí)行事務(wù)提交命令時(shí),就會(huì)進(jìn)入兩階段提交模式。兩階段提交分為prepare階段和commit兩個(gè)階段。流程如下 :這里面涉及到兩個(gè)重要的參數(shù):innodb_flush_log_at_trx_commit和sync

57、_binlog,參數(shù)可以設(shè)置不同的值,具體可以查看mysql的幫助手冊(cè)。我這里設(shè)置的是雙一模式(innodb_flush_log_at_trx_commit=1,sync_binlog=1),不同的模式區(qū)別在于,寫(xiě)文件調(diào)用write和落盤(pán)fsync調(diào)用的頻率不同,所導(dǎo)致的后果是mysqld 或 os crash后,不嚴(yán)格的設(shè)置可能會(huì)丟失事務(wù)的更新。雙一模式是最嚴(yán)格的模式,這種設(shè)置情況下,單機(jī)在任何情況下不會(huì)丟失事務(wù)更新。prepare階段:    1.設(shè)置undo state=TRX_UNDO_PREPARED; /trx_undo_set_state_at_prepare

58、調(diào)用    2.刷事務(wù)更新產(chǎn)生的redo日志;【步驟1產(chǎn)生的redo日志也會(huì)刷入】    commit階段:   1.將事務(wù)產(chǎn)生的binlog寫(xiě)入文件,刷入磁盤(pán);   2.設(shè)置undo頁(yè)的狀態(tài),置為T(mén)RX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE;  / trx_undo_set_state_at_finish調(diào)用   3.記錄事務(wù)對(duì)應(yīng)的binlog偏移,寫(xiě)入系統(tǒng)表空間; /trx_sys_update_mysql_binlo

59、g_offset調(diào)用        下面這部分是我抽象出來(lái)的源碼調(diào)用部分,大家可以通過(guò)單步調(diào)試方式,在關(guān)鍵函數(shù)中設(shè)置斷點(diǎn),來(lái)詳細(xì)了解這個(gè)過(guò)程。= prepare階段=MYSQL_BIN_LOG:prepare    ha_prepare_low    engine:binlog_prepareinnobase_xa_preparemysql:trx_prepare_for_mysql        

60、;        1.trx_undo_set_state_at_prepare    /設(shè)置undo段的標(biāo)記為T(mén)RX_UNDO_PREPARED                2.設(shè)置事務(wù)狀態(tài)為T(mén)RX_STATE_PREPARED         

61、       3.trx_flush_log_if_needed  /將產(chǎn)生的redolog刷入磁盤(pán)                      =commit階段=MYSQL_BIN_LOG:commit    ordered_commit   1.FLUSH_STAGE 

62、60;      flush_cache_to_file  /  刷binlog 2.SYNC_STAGE        sync_binlog_file    /Call fsync() to sync the disk. 3.COMMIT_STAGE        ha_commit_low   

63、0;                binlog_commit            innobase_commit                   trx_commit(trx)     

64、60;                               trx_write_serialisation_history(trx, mtr);  /更新binlog位點(diǎn),設(shè)置undo狀態(tài)         

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

66、;             mysqld可能在任何情況下crash,os也有可能出現(xiàn)問(wèn)題,另外若機(jī)器掉電,mysqld也會(huì)同樣掛掉。但是即使這樣,mysql仍然能保證數(shù)據(jù)庫(kù)的一致性。接下來(lái),我會(huì)結(jié)合上述流程,分析二階段提交如何保證這點(diǎn)的。下面給出幾種常見(jiàn)的場(chǎng)景,1.prepare階段,redo log落盤(pán)前,mysqld crash2.prepare階段,redo log落盤(pán)后,binlog落盤(pán)前,mysqld crashmit階段,binlog落盤(pán)后,mysqld crash      對(duì)于第一種情況,由于redo沒(méi)有落盤(pán),毫無(wú)疑問(wèn),事務(wù)的更新肯定沒(méi)有寫(xiě)入磁盤(pán),數(shù)據(jù)庫(kù)的一致性受影響;對(duì)于第二種情況,這時(shí)候redo log寫(xiě)入完成,但binlog還未寫(xiě)入,事務(wù)處于TRX_STATE_PREPARED狀態(tài),這是提交還是回滾呢?對(duì)于第三種情況,此時(shí),redo log和binlog都已經(jīng)落盤(pán),只是und

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論