MySQL事務(wù)機(jī)制是如何實(shí)現(xiàn)的

下文主要給大家?guī)?lái)MySQL事務(wù)機(jī)制是如何實(shí)現(xiàn)的,希望MySQL事務(wù)機(jī)制是如何實(shí)現(xiàn)的能夠帶給大家實(shí)際用處,這也是我編輯這篇文章的主要目的。好了,廢話不多說(shuō),大家直接看下文吧。

創(chuàng)新互聯(lián)公司10多年成都定制網(wǎng)頁(yè)設(shè)計(jì)服務(wù);為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì)及高端網(wǎng)站定制服務(wù),成都定制網(wǎng)頁(yè)設(shè)計(jì)及推廣,對(duì)成都塔吊租賃等多個(gè)方面擁有多年的網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。

            MySQL提供了兩種事務(wù)型的存儲(chǔ)引擎:InnoDB和NDB Cluster。另外還有一些第三方存儲(chǔ)引擎也支持事務(wù),比較知名的包括XtraDB和PBXT。下面以InnoDB來(lái)說(shuō)明。

            MySQL會(huì)最大程度的使用緩存機(jī)制來(lái)提高數(shù)據(jù)庫(kù)的訪問(wèn)效率,但是萬(wàn)一數(shù)據(jù)庫(kù)發(fā)生斷電,因?yàn)榫彺娴臄?shù)據(jù)沒(méi)有寫(xiě)入磁盤,導(dǎo)致緩存在內(nèi)存中的數(shù)據(jù)丟失而導(dǎo)致數(shù)據(jù)不一致怎么辦?

            InnoDB主要是通過(guò)事務(wù)日志實(shí)現(xiàn)ACID特性,事務(wù)日志可以幫助提高事務(wù)的效率。使用事務(wù)日志,存儲(chǔ)引擎在修改表的數(shù)據(jù)時(shí)只需要修改其內(nèi)存拷貝,再把該修改行為記錄到持久在硬盤上的事務(wù)日志中,而不用每次都將修改的數(shù)據(jù)本身持久到磁盤。下載

           事務(wù)日志采用追加的方式,因此寫(xiě)日志的操作是磁盤上一小塊區(qū)域的順序I/O,而不像隨機(jī)I/O需要在磁盤的多個(gè)地方移動(dòng)磁頭。所以事務(wù)日志的方式相對(duì)來(lái)說(shuō)要快得多。事務(wù)日志持久以后,內(nèi)存中被修改的數(shù)據(jù)在后臺(tái)可以慢慢的刷回磁盤。目前大多數(shù)存儲(chǔ)引擎是這樣實(shí)現(xiàn)的,我們稱之為預(yù)寫(xiě)式日志,即修改數(shù)據(jù)需要寫(xiě)兩次磁盤。

           事務(wù)日志包括重做日志redo和回滾日志undo,Redo記錄的是已經(jīng)全部完成的事務(wù),就是執(zhí)行了commit的事務(wù),記錄文件是ib_logfile0 ib_logfile1。Undo記錄的是已部分完成并且寫(xiě)入硬盤的未完成的事務(wù),默認(rèn)情況下回滾日志是記錄在表空間中的(共享表空間或者獨(dú)享表空間)。

           一般情況下,mysql在崩潰之后,重啟服務(wù),innodb通過(guò)回滾日志undo將所有已完成并寫(xiě)入磁盤的未完成事務(wù)進(jìn)行rollback,然后redo中的事務(wù)全部重新執(zhí)行一遍即可恢復(fù)數(shù)據(jù),但是隨著redo的量增加,每次從redo的第一條開(kāi)始恢復(fù)就會(huì)浪費(fèi)長(zhǎng)的時(shí)間,所以引入了checkpoint機(jī)制。

          一般業(yè)務(wù)運(yùn)行過(guò)程中,當(dāng)業(yè)務(wù)需要對(duì)某張表的某行數(shù)據(jù)進(jìn)行修改的時(shí)候,innodb會(huì)先將該數(shù)據(jù)從磁盤讀取到緩存中去,然后在緩存中對(duì)這條數(shù)據(jù)進(jìn)行修改,這樣緩存中的數(shù)據(jù)就和磁盤的數(shù)據(jù)不一致了,這個(gè)時(shí)候緩存中的數(shù)據(jù)就稱為dirty page,只有當(dāng)臟頁(yè)統(tǒng)一刷新到磁盤中才會(huì)是clean page。下載

          Checkpoint:如果在某個(gè)時(shí)間點(diǎn),臟頁(yè)的數(shù)據(jù)被刷新到了磁盤,系統(tǒng)就把這個(gè)刷新的時(shí)間點(diǎn)記錄到redo log的結(jié)尾位置,在進(jìn)行恢復(fù)數(shù)據(jù)的時(shí)候,checkpoint時(shí)間點(diǎn)之前的數(shù)據(jù)就不需要進(jìn)行恢復(fù)了,可以縮短時(shí)間。

 MySQL事務(wù)機(jī)制是如何實(shí)現(xiàn)的

Innodb_log_buffer_size 重做日志緩存大小

Innodb_log_file_size redo log文件大小  文件越大 數(shù)據(jù)恢復(fù)的時(shí)間越長(zhǎng)

Innodb_log_file_group redo log文件數(shù)量 默認(rèn)是2個(gè) ib_logfile0 ib_logfile1

 

           事務(wù)日志的的機(jī)制實(shí)際上是滿足的事務(wù)的原子性和持久性,即要么都成功,要么都失敗。而談到事務(wù)的一致性和隔離性,就要談到“鎖”了。

           InnoDB采用的是兩階段鎖定協(xié)議。在事務(wù)執(zhí)行過(guò)程中,隨時(shí)都可以執(zhí)行鎖定,鎖只有在執(zhí)行COMMIT或ROLLBACK時(shí)才會(huì)釋放,并且所有的鎖同一時(shí)刻釋放。InnoDB會(huì)根據(jù)隔離級(jí)別在需要的時(shí)候自動(dòng)加鎖。

           MySQL的大多數(shù)事務(wù)型存儲(chǔ)引擎實(shí)現(xiàn)的都不是簡(jiǎn)單的行級(jí)鎖?;谔嵘l(fā)性能的考慮,它們一般都同時(shí)實(shí)現(xiàn)了多版本并發(fā)控制(MVCC)。MVCC實(shí)現(xiàn)了非阻塞的讀操作,寫(xiě)操作也只鎖定必要的行。MVCC的實(shí)現(xiàn),是通過(guò)保存數(shù)據(jù)在某個(gè)時(shí)間點(diǎn)的快照來(lái)實(shí)現(xiàn)的。對(duì)于InnoDB,是通過(guò)在每行記錄后面保存兩個(gè)隱藏的列來(lái)實(shí)現(xiàn)的。這兩個(gè)列,一個(gè)保存了行的創(chuàng)建時(shí)間,一個(gè)保存了行的過(guò)期時(shí)間(或刪除時(shí)間)。當(dāng)然存儲(chǔ)的并不是實(shí)際時(shí)間值,而是系統(tǒng)版本號(hào)。每開(kāi)始一個(gè)新的事務(wù),系統(tǒng)版本號(hào)都會(huì)自動(dòng)遞增。事務(wù)開(kāi)始時(shí)刻的系統(tǒng)版本號(hào)會(huì)作為事務(wù)的版本號(hào),用來(lái)和查詢到的每行記錄的版本號(hào)進(jìn)行比較。下面看一下在MySQL默認(rèn)隔離級(jí)別REPEATABLE READ下,MVCC具體是如何操作的。下載

  SELECT

  InnoDB會(huì)根據(jù)以下兩個(gè)條件檢查每行記錄:

  a. InnoDB只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行(也就是,行的系統(tǒng)版本號(hào)<=事務(wù)的系統(tǒng)版本好),這樣可     以確保事務(wù)讀取的行,要么是在事務(wù)開(kāi)始前已經(jīng)存在的,要么是事務(wù)自身插入或修改過(guò)的。

  b. 行的刪除版本要么未定義,要么大于當(dāng)前事務(wù)版本號(hào)。這樣可以確保事務(wù)讀取到的行,在事務(wù)開(kāi)始之前未被   刪除。

  只有符合上述兩個(gè)條件的記錄,才能返回作為查詢結(jié)果。

  INSERT

  InnoDB為新插入的每一行保存當(dāng)前系統(tǒng)版本號(hào)作為行版本號(hào)。

  DELETE

  InnoDB為刪除的每一行保存當(dāng)前系統(tǒng)版本號(hào)作為刪除標(biāo)識(shí)。

  UPDATE

  InnoDB為插入一行新記錄,保存當(dāng)前系統(tǒng)版本號(hào)作為行版本號(hào),同時(shí)保存當(dāng)前系統(tǒng)版本號(hào)到原來(lái)的行作為行     刪除標(biāo)識(shí)。

  保存這兩個(gè)額外系統(tǒng)版本號(hào),使大多數(shù)讀操作都可以不用加鎖。這樣讀操作簡(jiǎn)單而性能好,也能保證讀到符合標(biāo)準(zhǔn)的行。不足之處是需要額外的存儲(chǔ)空間,需要做更多的行檢查工作,以及一些額外的維護(hù)工作。另外,MVCC只在REPEATABLE READ和READ COMMITED兩個(gè)隔離級(jí)別下工作。其他兩個(gè)隔離級(jí)別都和MVCC不兼容,因?yàn)镽EAD UNCOMMITED縱是讀取到最新的數(shù)據(jù)行,而不是符合當(dāng)前事務(wù)版本的數(shù)據(jù)行,而SERIALIZABLE則會(huì)對(duì)所有讀取的行都加鎖。

  好了,相信你對(duì)MySQL事務(wù)實(shí)現(xiàn)機(jī)制有些了解了,下面摘抄兩段知乎上關(guān)于ACID的理解。下載

--------------

講道理

定義:數(shù)據(jù)庫(kù)一致性(Database Consistency)是指事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變到另一個(gè)一致性狀態(tài)。

數(shù)據(jù)庫(kù)狀態(tài)如何變化?每一次數(shù)據(jù)變更就會(huì)導(dǎo)致數(shù)據(jù)庫(kù)的狀態(tài)遷移。如果數(shù)據(jù)庫(kù)的初始狀態(tài)是C0,第一次事務(wù)T1的提交就會(huì)導(dǎo)致系統(tǒng)生成一個(gè)SYSTEM CHANGE NUMBER(SCN),這是數(shù)據(jù)庫(kù)狀態(tài)從C0轉(zhuǎn)變成C1。執(zhí)行第二個(gè)事務(wù)T2的時(shí)候數(shù)據(jù)庫(kù)狀態(tài)從C1變成C2,以此類推,執(zhí)行第Tn次事務(wù)的時(shí)候數(shù)據(jù)庫(kù)狀態(tài)由C(n-1)變成Cn。

定義一致性主要有2個(gè)方面,一致讀和一致寫(xiě)。

一致寫(xiě):事務(wù)執(zhí)行的數(shù)據(jù)變更只能基于上一個(gè)一致的狀態(tài),且只能體現(xiàn)在一個(gè)狀態(tài)中。T(n)的變更結(jié)果只能基于C(n-1),C(n-2), ...C(1)狀態(tài),且只能體現(xiàn)在C(n)狀態(tài)中。也就是說(shuō),一個(gè)狀態(tài)只能有一個(gè)事務(wù)變更數(shù)據(jù),不允許有2個(gè)或者2個(gè)以上事務(wù)在一個(gè)狀態(tài)中變更數(shù)據(jù)。至于具體一致寫(xiě)基于哪個(gè)狀態(tài),需要判斷T(n)事務(wù)是否和T(n-1),T(n-2),...T(1)有依賴關(guān)系。

一致讀:事務(wù)讀取數(shù)據(jù)只能從一個(gè)狀態(tài)中讀取,不能從2個(gè)或者2個(gè)以上狀態(tài)讀取。也就是T(n)只能從C(n-1),C(n-2)... C(1)中的一個(gè)狀態(tài)讀取數(shù)據(jù),不能一部分?jǐn)?shù)據(jù)讀取自C(n-1),而另一部分?jǐn)?shù)據(jù)讀取自C(n-2)。

擺事實(shí)

一致寫(xiě):
定義100個(gè)事務(wù)T(1)...T(100)實(shí)現(xiàn)相同的邏輯 update table set i=i+1,i的初始值是0,那么并發(fā)執(zhí)行這100個(gè)事務(wù)之后i的值是多少?可能很容易想到是100。那么怎么從一致性角度去理解呢?

數(shù)據(jù)庫(kù)隨機(jī)調(diào)度到T(50)執(zhí)行,此時(shí)數(shù)據(jù)庫(kù)狀態(tài)是C(0),而其它事務(wù)都和T(50)有依賴關(guān)系,根據(jù)寫(xiě)一致性原理,其它事務(wù)必須等到T(50)執(zhí)行完畢后數(shù)據(jù)庫(kù)狀態(tài)變?yōu)镃(1)才可以執(zhí)行。因此數(shù)據(jù)庫(kù)利用鎖機(jī)制阻塞其它事務(wù)的執(zhí)行。直到T(50)執(zhí)行完畢,數(shù)據(jù)庫(kù)狀態(tài)從C(0)遷移到C(1)。數(shù)據(jù)庫(kù)喚醒其它事務(wù)后隨機(jī)調(diào)度到T(89)執(zhí)行,以此類推直到所有事務(wù)調(diào)度執(zhí)行完畢,數(shù)據(jù)庫(kù)狀態(tài)最終變?yōu)镃(100)。下載
一致讀:
還是上面的例子,假設(shè)T(1)...T(100)順序執(zhí)行,在不同的時(shí)機(jī)執(zhí)行select i from table,我們看到i的值是什么?
1. T(1)的執(zhí)行過(guò)程中。數(shù)據(jù)庫(kù)狀態(tài)尚未遷移,讀到的i=0

2. T(1)執(zhí)行完畢,T(2)的執(zhí)行過(guò)程中,數(shù)據(jù)庫(kù)狀態(tài)遷移至C(1),讀到的i=1 

 

---------------

講數(shù)據(jù)庫(kù)事務(wù)一致性怎么能不提數(shù)據(jù)庫(kù)的ACID特性。
首先介紹事務(wù),什么是事務(wù),事務(wù)就是DBMS當(dāng)中用戶程序的任何一次執(zhí)行,事務(wù)室DBMS能看到的基本修改單元。

事務(wù)是指對(duì)系統(tǒng)進(jìn)行的一組操作,為了保證系統(tǒng)的完整性,事務(wù)需要具有ACID特性,具體如下:
1. 原子性(Atomic)
一個(gè)事務(wù)包含多個(gè)操作,這些操作要么全部執(zhí)行,要么全都不執(zhí)行。實(shí)現(xiàn)事務(wù)的原子性,要支持回滾操作,在某個(gè)操作失敗后,回滾到事務(wù)執(zhí)行之前的狀態(tài)。
回滾實(shí)際上是一個(gè)比較高層抽象的概念,大多數(shù)DB在實(shí)現(xiàn)事務(wù)時(shí),是在事務(wù)操作的數(shù)據(jù)快照上進(jìn)行的(比如,MVCC),并不修改實(shí)際的數(shù)據(jù),如果有錯(cuò)并不會(huì)提交,所以很自然的支持回滾。
而在其他支持簡(jiǎn)單事務(wù)的系統(tǒng)中,不會(huì)在快照上更新,而直接操作實(shí)際數(shù)據(jù)??梢韵阮A(yù)演一邊所有要執(zhí)行的操作,如果失敗則這些操作不會(huì)被執(zhí)行,通過(guò)這種方式很簡(jiǎn)單的實(shí)現(xiàn)了原子性。下載


2. 一致性(Consistency)
一致性是指事務(wù)使得系統(tǒng)從一個(gè)一致的狀態(tài)轉(zhuǎn)換到另一個(gè)一致?tīng)顟B(tài)。事務(wù)的一致性決定了一個(gè)系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)的復(fù)雜度。事務(wù)可以不同程度的一致性:
強(qiáng)一致性:讀操作可以立即讀到提交的更新操作。
弱一致性:提交的更新操作,不一定立即會(huì)被讀操作讀到,此種情況會(huì)存在一個(gè)不一致窗口,指的是讀操作可以讀到最新值的一段時(shí)間。
最終一致性:是弱一致性的特例。事務(wù)更新一份數(shù)據(jù),最終一致性保證在沒(méi)有其他事務(wù)更新同樣的值的話,最終所有的事務(wù)都會(huì)讀到之前事務(wù)更新的最新值。如果沒(méi)有錯(cuò)誤發(fā)生,不一致窗口的大小依賴于:通信延遲,系統(tǒng)負(fù)載等。
其他一致性變體還有:
單調(diào)一致性:如果一個(gè)進(jìn)程已經(jīng)讀到一個(gè)值,那么后續(xù)不會(huì)讀到更早的值。
會(huì)話一致性:保證客戶端和云服務(wù)器交互的會(huì)話過(guò)程中,讀操作可以讀到更新操作后的最新值。

3. 隔離性(Isolation)下載

并發(fā)事務(wù)之間互相影響的程度,比如一個(gè)事務(wù)會(huì)不會(huì)讀取到另一個(gè)未提交的事務(wù)修改的數(shù)據(jù)。在事務(wù)并發(fā)操作時(shí),可能出現(xiàn)的問(wèn)題有:
臟讀:事務(wù)A修改了一個(gè)數(shù)據(jù),但未提交,事務(wù)B讀到了事務(wù)A未提交的更新結(jié)果,如果事務(wù)A提交失敗,事務(wù)B讀到的就是臟數(shù)據(jù)。
不可重復(fù)讀:在同一個(gè)事務(wù)中,對(duì)于同一份數(shù)據(jù)讀取到的結(jié)果不一致。比如,事務(wù)B在事務(wù)A提交前讀到的結(jié)果,和提交后讀到的結(jié)果可能不同。不可重復(fù)讀出現(xiàn)的原因就是事務(wù)并發(fā)修改記錄,要避免這種情況,最簡(jiǎn)單的方法就是對(duì)要修改的記錄加鎖,這回導(dǎo)致鎖競(jìng)爭(zhēng)加劇,影響性能。另一種方法是通過(guò)MVCC可以在無(wú)鎖的情況下,避免不可重復(fù)讀。
幻讀:在同一個(gè)事務(wù)中,同一個(gè)查詢多次返回的結(jié)果不一致。事務(wù)A新增了一條記錄,事務(wù)B在事務(wù)A提交前后各執(zhí)行了一次查詢操作,發(fā)現(xiàn)后一次比前一次多了一條記錄。幻讀是由于并發(fā)事務(wù)增加記錄導(dǎo)致的,這個(gè)不能像不可重復(fù)讀通過(guò)記錄加鎖解決,因?yàn)閷?duì)于新增的記錄根本無(wú)法加鎖。需要將事務(wù)串行化,才能避免幻讀。
事務(wù)的隔離級(jí)別從低到高有:
Read Uncommitted:最低的隔離級(jí)別,什么都不需要做,一個(gè)事務(wù)可以讀到另一個(gè)事務(wù)未提交的結(jié)果。所有的并發(fā)事務(wù)問(wèn)題都會(huì)發(fā)生。
Read Committed:只有在事務(wù)提交后,其更新結(jié)果才會(huì)被其他事務(wù)看見(jiàn)??梢越鉀Q臟讀問(wèn)題。
Repeated Read:在一個(gè)事務(wù)中,對(duì)于同一份數(shù)據(jù)的讀取結(jié)果總是相同的,無(wú)論是否有其他事務(wù)對(duì)這份數(shù)據(jù)進(jìn)行操作,以及這個(gè)事務(wù)是否提交??梢越鉀Q臟讀、不可重復(fù)讀。
Serialization:事務(wù)串行化執(zhí)行,隔離級(jí)別最高,犧牲了系統(tǒng)的并發(fā)性??梢越鉀Q并發(fā)事務(wù)的所有問(wèn)題。
通常,在工程實(shí)踐中,為了性能的考慮會(huì)對(duì)隔離性進(jìn)行折中。

4. 持久性(Durability)
事務(wù)提交后,對(duì)系統(tǒng)的影響是永久的。

對(duì)于以上關(guān)于MySQL事務(wù)機(jī)制是如何實(shí)現(xiàn)的,大家是不是覺(jué)得非常有幫助。如果需要了解更多內(nèi)容,請(qǐng)繼續(xù)關(guān)注我們的行業(yè)資訊,相信你會(huì)喜歡上這些內(nèi)容的。

網(wǎng)站欄目:MySQL事務(wù)機(jī)制是如何實(shí)現(xiàn)的
轉(zhuǎn)載來(lái)于:http://muchs.cn/article38/ihpgpp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、App設(shè)計(jì)、定制網(wǎng)站、網(wǎng)站收錄、網(wǎng)站導(dǎo)航、用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)