MYSQL专题-MySQL事务实现原理
用過事務(wù)的伙伴大概都知道它的相關(guān)特性主要有四個(gè):原子性(Atomicity),一致性(Consistency),隔離型(Isolation)以及持久性(Durability)。今天想跟大家一起研究下事務(wù)內(nèi)部到底是怎么實(shí)現(xiàn)的。首先大家想一想,為什么需要事務(wù)?其實(shí)使用事務(wù)一方面為了保證數(shù)據(jù)的可靠性,另一方面是對(duì)于并發(fā)處理提供了很好的解決方案:
- 可靠性:數(shù)據(jù)庫(kù)要保證當(dāng)insert或update操作時(shí)拋異常或者數(shù)據(jù)庫(kù)crash的時(shí)候需要保障數(shù)據(jù)的操作前后的一致,想要做到這個(gè),我需要知道我修改之前和修改之后的狀態(tài),所以就有了undo log和redo log。
- 并發(fā)處理:當(dāng)多個(gè)并發(fā)請(qǐng)求過來,并且其中有一個(gè)請(qǐng)求是對(duì)數(shù)據(jù)修改操作的時(shí)候會(huì)有影響,為了避免讀到臟數(shù)據(jù),所以需要對(duì)事務(wù)之間的讀寫進(jìn)行隔離,至于隔離到啥程度得看業(yè)務(wù)系統(tǒng)的場(chǎng)景了,實(shí)現(xiàn)這個(gè)就得用MySQL 的隔離級(jí)別。
上面提到了兩個(gè)文件:undo log和redo log,大家對(duì)這個(gè)不太了解的可以看我的另一篇文章MYSQL專題-MySQL三大日志binlog、redo log和undo log。其實(shí)除了這兩個(gè),MYSQL還提供了一個(gè)MVVC(多版本并發(fā)控制),這里會(huì)給大家再介紹一下undo log,redo log和MVVC,然后基于這三個(gè)我們?cè)僦v實(shí)現(xiàn)事務(wù)的原理。希望大家可以認(rèn)真耐心地看完。文章主要分為四個(gè)部分:
1 事務(wù)的介紹
1.1 為什么需要事務(wù)
以轉(zhuǎn)賬案例為例進(jìn)行講解。假設(shè)現(xiàn)在要從A賬戶向B賬戶中轉(zhuǎn)入500 塊,當(dāng)進(jìn)行轉(zhuǎn)賬時(shí),需要先從銀行賬戶A中取出錢,然后再存入銀行賬戶B中,SQL如下:
// 第一步:A賬戶余額減少減少1000 update balance set money = money -500 where name= ‘A’; // 第二步:B賬戶余額增加1000 update balance set money = money +500 where name= ‘B’;如果在完成了第1步的時(shí)候突然宕機(jī)了,A的錢減少了而B的錢沒有增加,那A豈不是白白丟了500 塊。這時(shí)候就需要用到我們的事務(wù)了,開啟事務(wù)后SQL如下:
// 第一步:開始事務(wù) start transaction; // 第二步:A賬戶余額減少減少1000 update balance set money = money -500 where name= ‘A’; // 第三步:B賬戶余額增加1000 update balance set money = money +500 where name= ‘B’; // 第四步:提交事務(wù) commit;1.2 什么是事務(wù)
有了以上的案例,接下里回答什么是事務(wù)。事務(wù)(Transaction)是訪問和更新數(shù)據(jù)庫(kù)的程序執(zhí)行單元;事務(wù)中可能包含一個(gè)或多個(gè)sql語句,這些語句要么都執(zhí)行成功,要么全部執(zhí)行失敗。
1.3 事務(wù)的四大特性(ACID)
開篇我們就提到事務(wù)具有四大特性,接下里給大家簡(jiǎn)單描述以下:
- 原子性(Atomicity,或稱不可分割性)
- 一個(gè)事務(wù)必須被視為一個(gè)不可分割的最小工作單元,整個(gè)事務(wù)中所有的操作要么全部提交成功,要么全部失敗回滾,對(duì)于一個(gè)事務(wù)來說,不可能只執(zhí)行其中的一部分操作。
- 一致性(Consistency)
- 數(shù)據(jù)庫(kù)總是從一個(gè)一致性的狀態(tài)轉(zhuǎn)換到另外一個(gè)一致性的狀態(tài),在事務(wù)開始之前和之后,數(shù)據(jù)庫(kù)的完整性約束沒有被破壞。
- 隔離性(Isolation)
- 事務(wù)內(nèi)部的操作與其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。嚴(yán)格的隔離性,對(duì)應(yīng)了事務(wù)隔離級(jí)別中的Serializable (可串行化),但實(shí)際應(yīng)用中出于性能方面的考慮很少會(huì)使用可串行化。
- 持久性(Durability)
- 事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)的改變就應(yīng)該是永久性的,接下來的其他操作或故障不應(yīng)該對(duì)其有任何影響。
1.4 事務(wù)的隔離級(jí)別
在上面我們提到了隔離性,但實(shí)際上隔離性比想象的要復(fù)雜的多。在SQL標(biāo)準(zhǔn)中定義了四種隔離級(jí)別,每一種隔離級(jí)別都規(guī)定了一個(gè)事務(wù)所做的修改,哪些在事務(wù)內(nèi)和事務(wù)間是可見的,哪些是不可見的,較低級(jí)別的隔離通常可以執(zhí)行更高的并發(fā),系統(tǒng)的開銷也更低。MySQL的默認(rèn)隔離級(jí)別是可重復(fù)讀(REPEATABLE READ)。
-
讀未提交(READ UNCOMMITTED)
- 在這個(gè)隔離級(jí)別下,事務(wù)的修改即使沒有提交,對(duì)其他事務(wù)也是可見的。事務(wù)可以讀取未提交的數(shù)據(jù),這也被稱之為臟讀。這個(gè)級(jí)別會(huì)帶來很多問題,從性能上來說,READ UNCOMMITTED不會(huì)比其他的級(jí)別好太多,但是卻會(huì)帶來很多問題,除非真的有非常必要的理由,在實(shí)際應(yīng)用中一般很少使用。
-
讀已提交(REDA COMMITED)
- 大多數(shù)數(shù)據(jù)系統(tǒng)的默認(rèn)隔離級(jí)別都是REDA COMMITED(MySql不是),REDA COMMITED滿足前面提到的隔離性的簡(jiǎn)單定義:一個(gè)事務(wù)開始時(shí),只能看到已經(jīng)提交的事務(wù)所做的修改。換句話說,一個(gè)事物從開始直到提交前,所做的修改對(duì)其他事務(wù)不可見。這個(gè)級(jí)別有時(shí)候也叫做不可重復(fù)讀,因?yàn)閳?zhí)行兩次相同的查詢可能會(huì)得到不同的結(jié)果。
-
可重復(fù)讀(REPEATABLE READ)
- REPEATABLE READ解決了臟讀以及不可重復(fù)度的問題。該級(jí)別保證了同一個(gè)事務(wù)多次讀取同樣記錄的結(jié)果是一致的。但是理論上,可重復(fù)度還是無法解決另外一個(gè)幻讀的問題。所謂幻讀,指的是當(dāng)某個(gè)事務(wù)在讀取某個(gè)范圍內(nèi)的記錄時(shí),另外一個(gè)事務(wù)又在該范圍內(nèi)插入了新的記錄,當(dāng)之前的事務(wù)再次讀取該范圍的記錄時(shí),就會(huì)產(chǎn)生幻讀。不可重復(fù)讀跟幻讀的區(qū)別在于,前者是數(shù)據(jù)發(fā)生了變化,后者是數(shù)據(jù)的行數(shù)發(fā)生了變化。
-
串行化(SERIALIZABLE)
- SERIALIZABLE是最高的隔離級(jí)別,它通過強(qiáng)制事務(wù)串行執(zhí)行,避免前面說的幻讀。簡(jiǎn)單來說SERIALIZABLE會(huì)在讀取的每一行數(shù)據(jù)上都加鎖,所以可能會(huì)導(dǎo)致大量的超時(shí)和鎖爭(zhēng)用的問題。實(shí)際應(yīng)用中也很少使用這個(gè)隔離級(jí)別,只有在非常需要確保數(shù)據(jù)一致性而且可以接受沒有并發(fā)的情況下,才考慮此級(jí)別。
1.5 保存點(diǎn)
我們可以在事務(wù)執(zhí)行的過程中定義保存點(diǎn),在回滾時(shí)直接指定回滾到指定的保存點(diǎn)而不是事務(wù)開始之初,有點(diǎn)像我們玩游戲的時(shí)候可以存檔而不是每次都要重新再來。語法如下:
SAVEPOINT 保存點(diǎn)名稱;當(dāng)我們想回滾到某個(gè)保存點(diǎn)時(shí),可以使用下邊這個(gè)語句(下邊語句中的單詞WORK和SAVEPOINT是可有可無的):
ROLLBACK [WORK] TO [SAVEPOINT] 保存點(diǎn)名稱;2 redo log與undo log
2.1 redo log
redo log叫做重做日志,用來實(shí)現(xiàn)事務(wù)的持久性,當(dāng)宕機(jī)或斷電時(shí)用來恢復(fù)數(shù)據(jù)。該日志文件由兩部分組成:重做日志緩沖(redo log buffer)以及重做日志文件(redo log),前者是在內(nèi)存中,后者在磁盤中。當(dāng)事務(wù)提交之后會(huì)把所有修改信息都會(huì)存到該日志中。我們假設(shè)有這樣一個(gè)場(chǎng)景:用戶需要將銀行賬戶里的錢存500百塊錢存到自己的理財(cái)賬戶中去。這里由兩張表,一張銀行卡賬戶信息表,包含賬戶id,賬戶名和賬戶余額,另一張表是理財(cái)賬戶表,包含理財(cái)賬戶id,理財(cái)賬戶名稱和理財(cái)賬戶余額。為了方便我們假設(shè)用戶名稱不允許重復(fù)。則假設(shè)銀行卡賬戶信息表里的余額為1000,理財(cái)賬戶表的余額為0,則需要將銀行賬戶信息中的余額減去600 ,然后將理財(cái)表里的余額加上600,對(duì)應(yīng)的sql語句如下:
start transaction; update bank set balance = balance - 600 where name="kmli"; // 生成 重做日志 balance=400 update finance set amount = amount + 600 where name="kmli"; // 生成 重做日志 amount=600 commit;在以上依據(jù)中標(biāo)注了redo log生成的時(shí)機(jī)。為了更好的幫助大家理解,這里畫一個(gè)流程圖:
我們知道,mysql 為了提升性能并不會(huì)把每次的修改都實(shí)時(shí)同步到磁盤,而是會(huì)先存到Boffer Pool(緩沖池)里頭,把這個(gè)當(dāng)作緩存來用,然后使用后臺(tái)線程去做緩沖池和磁盤之間的同步。如果還沒來的同步的時(shí)候宕機(jī)或斷電了怎么辦?對(duì)應(yīng)流程圖中紅色的操作。這樣會(huì)導(dǎo)致丟部分已提交事務(wù)的修改信息!所以引入了redo log來記錄已成功提交事務(wù)的修改信息,并且會(huì)把redo log持久化到磁盤,系統(tǒng)重啟之后在讀取redo log恢復(fù)最新數(shù)據(jù)。
2.2 undo log
undo log 叫做回滾日志,用于記錄數(shù)據(jù)被修改前的信息,保障未提交事務(wù)的原子性。每次寫入數(shù)據(jù)或者修改數(shù)據(jù)之前都會(huì)把修改前的信息記錄到 undo log。正好跟前面所說的重做日志所記錄的相反,重做日志記錄數(shù)據(jù)被修改后的信息。undo log主要記錄的是數(shù)據(jù)的邏輯變化,為了在發(fā)生錯(cuò)誤時(shí)回滾之前的操作,需要將之前的操作都記錄下來,然后在發(fā)生錯(cuò)誤時(shí)才可以回滾。還是以上面的例子為例進(jìn)行說明:
start transaction; // 生成 回滾日志 balance=1000 update bank set balance = balance - 600 where name="kmli"; // 生成 回滾日志 amount=0 update finance set amount = amount + 600 where name="kmli"; commit;在以上依據(jù)中標(biāo)注了undo log生成的時(shí)機(jī)。為了更好的幫助大家理解,這里畫一個(gè)流程圖:
undo log 記錄事務(wù)修改之前版本的數(shù)據(jù)信息,因此假如由于系統(tǒng)錯(cuò)誤或者rollback操作而回滾的話可以根據(jù)undo log的信息來進(jìn)行回滾到?jīng)]被修改前的狀態(tài)。
3 mysql鎖機(jī)制(InnoDB)以及MVCC
3.1 mysql鎖鎖機(jī)制
當(dāng)有多個(gè)請(qǐng)求來讀取表中的數(shù)據(jù)時(shí)可以不采取任何操作,但是多個(gè)請(qǐng)求里有讀請(qǐng)求,又有修改請(qǐng)求時(shí)必須有一種措施來進(jìn)行并發(fā)控制,不然很有可能會(huì)造成不一致。Mysql中通過各種鎖的組合來對(duì)讀寫請(qǐng)求進(jìn)行控制,這里只簡(jiǎn)單介紹幾類,后面我們也會(huì)出文章對(duì)于其中的鎖進(jìn)行具體的分析。
- 讀鎖跟寫鎖
- 讀鎖:可以共享,可以叫共享鎖(shared lock),多個(gè)讀請(qǐng)求可以共享一把鎖讀數(shù)據(jù),不會(huì)造成阻塞,只能讀不能修改。。
- 寫鎖:可以叫排他鎖(exclusive lock),寫鎖會(huì)排斥其他所有獲取鎖的請(qǐng)求,一直阻塞,直到寫入完成釋放鎖。
通過讀寫鎖,可以做到讀讀可以并行,但是不能做到寫讀,寫寫并行 事務(wù)的隔離性就是根據(jù)讀寫鎖來實(shí)現(xiàn)的。
- 行鎖跟表鎖
- 行鎖:只鎖定需要操作的數(shù)據(jù),并發(fā)性能好。
- 表鎖:在操作數(shù)據(jù)時(shí)會(huì)鎖定整張表,并發(fā)性能較差。
由于加鎖本身需要消耗資源(獲得鎖、檢查鎖、釋放鎖等都需要消耗資源),因此在鎖定數(shù)據(jù)較多情況下使用表鎖可以節(jié)省大量資源。MySQL中不同的存儲(chǔ)引擎支持的鎖是不一樣的,例如MyIsam只支持表鎖,而InnoDB同時(shí)支持表鎖和行鎖,且出于性能考慮,絕大多數(shù)情況下使用的都是行鎖。
3.2 MVCC
MVCC (MultiVersion Concurrency Control) 叫做多版本并發(fā)控制。InnoDB的 MVCC ,是通過在每行記錄的后面保存兩個(gè)隱藏的列來實(shí)現(xiàn)的。這兩個(gè)列, 一個(gè)保存了行的創(chuàng)建時(shí)間,一個(gè)保存了行的過期時(shí)間,當(dāng)然存儲(chǔ)的并不是實(shí)際的時(shí)間值,而是系統(tǒng)版本號(hào)。通過數(shù)據(jù)多版本來做到讀寫分離,從而實(shí)現(xiàn)不加鎖讀進(jìn)而做到讀寫并行。(我們?cè)诤笃跁?huì)專門寫一篇關(guān)于MVCC的文章)
4 事務(wù)的實(shí)現(xiàn)原理
前面講的重做日志,回滾日志以及鎖技術(shù)就是實(shí)現(xiàn)事務(wù)的基礎(chǔ):
- 事務(wù)的原子性是通過 undo log 來實(shí)現(xiàn)的
- 事務(wù)的持久性性是通過 redo log 來實(shí)現(xiàn)的
- 事務(wù)的隔離性是通過 (讀寫鎖+MVCC)來實(shí)現(xiàn)的
- 事務(wù)的一致性是通過原子性,持久性,隔離性來實(shí)現(xiàn)的
MySQL中不是所有的存儲(chǔ)引擎都支持事務(wù),MyISAM就不支持事務(wù),實(shí)際上支持事務(wù)的只有InnoDB跟NDB Cluster,本文關(guān)于事務(wù)的分析都是基于InnoDB。在分析事務(wù)的實(shí)現(xiàn)原理之前我們介紹一下InnoDB的相關(guān)知識(shí)。
- InnoDB是一個(gè)將表中的數(shù)據(jù)存儲(chǔ)到磁盤上的存儲(chǔ)引擎,所以即使關(guān)機(jī)后重啟我們的數(shù)據(jù)還是存在的。而真正處理數(shù)據(jù)的過程是發(fā)生在內(nèi)存中的,所以需要把磁盤中的數(shù)據(jù)加載到內(nèi)存中,如果是處理寫入或修改請(qǐng)求的話,還需要把內(nèi)存中的內(nèi)容刷新到磁盤上。而我們知道讀寫磁盤的速度非常慢,和內(nèi)存讀寫差了幾個(gè)數(shù)量級(jí),所以當(dāng)我們想從表中獲取某些記錄時(shí),InnoDB存儲(chǔ)引擎需要一條一條的把記錄從磁盤上讀出來么?不,那樣會(huì)慢死,InnoDB采取的方式是:將數(shù)據(jù)劃分為若干個(gè)頁,以頁作為磁盤和內(nèi)存之間交互的基本單位,InnoDB中頁的大小一般為 16 KB。也就是在一般情況下,一次最少?gòu)拇疟P中讀取16KB的內(nèi)容到內(nèi)存中,一次最少把內(nèi)存中的16KB內(nèi)容刷新到磁盤中。
- InnoDB作為MySQL的存儲(chǔ)引擎,數(shù)據(jù)是存放在磁盤中的,但如果每次讀寫數(shù)據(jù)都需要磁盤IO,效率會(huì)很低。為此,InnoDB提供了緩存(Buffer Pool),Buffer Pool中包含了磁盤中部分?jǐn)?shù)據(jù)頁的映射,作為訪問數(shù)據(jù)庫(kù)的緩沖:當(dāng)從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)時(shí),會(huì)首先從Buffer Pool中讀取,如果Buffer Pool中沒有,則從磁盤讀取后放入Buffer Pool;當(dāng)向數(shù)據(jù)庫(kù)寫入數(shù)據(jù)時(shí),會(huì)首先寫入Buffer Pool,Buffer Pool中修改的數(shù)據(jù)會(huì)定期刷新到磁盤中(這一過程稱為刷臟)。
- InnoDB存儲(chǔ)引擎文件主要可以分為兩類,表空間文件及重做日志文件(redo log file),表空間文件又可以細(xì)分為兩類,共享表空間跟獨(dú)立表空間。「undo log位于共享表空間中的undo段中」,每個(gè)表空間都被劃分成了若干個(gè)頁面,「凡是頁面的讀寫都在buffer pool中進(jìn)行,這意味著undo log也需要先寫入到buffer pool,所以u(píng)ndo log的生成也需要持久化,也就是說undo log的生成需要記錄對(duì)應(yīng)的redo log」。(注意:不是所有的undo log的生成都會(huì)產(chǎn)生對(duì)應(yīng)的redo log,對(duì)于操作臨時(shí)表生成的undo log并不會(huì)生成對(duì)應(yīng)的undo log,因?yàn)樾薷呐R時(shí)表而產(chǎn)生的undo日志只需要在系統(tǒng)運(yùn)行過程中有效,如果系統(tǒng)奔潰了,那么在重啟時(shí)也不需要恢復(fù)這些undo日志所在的頁面,所以在寫針對(duì)臨時(shí)表的Undo頁面時(shí),并不需要記錄相應(yīng)的redo日志。)
我們要探究MySQL中事務(wù)的實(shí)現(xiàn)原理,實(shí)際上就是要弄明白它的ACID特性是如何實(shí)現(xiàn)的。正如上面的描述,ACID中的一致性是事務(wù)的最終目標(biāo),前面提到的原子性、持久性和隔離性,都是為了保證數(shù)據(jù)庫(kù)狀態(tài)的一致性。所以我們要分析的就是MySQL的原子性、持久性和隔離性的實(shí)現(xiàn)原理。接下來我們對(duì)事務(wù)的每一特性的原理進(jìn)行說明。
4.1 原子性實(shí)現(xiàn)原理
前面提到了,所謂原子性就是指整個(gè)事務(wù)是一個(gè)不可分隔的整體,組成事務(wù)的一組SQL要么全部成功,要么全部失敗,要達(dá)到這個(gè)目的就意味著當(dāng)某一個(gè)SQL執(zhí)行失敗時(shí),我們要能夠撤銷掉其它SQL的執(zhí)行結(jié)果,在MySQL中這是依賴undo log(回滾日志)來實(shí)現(xiàn)。
undo log屬于邏輯日志(redo log屬于物理日志,記錄的是數(shù)據(jù)頁的情況),我們可以這么認(rèn)為,當(dāng)delete一條記錄時(shí),undo log中會(huì)記錄一條對(duì)應(yīng)的insert記錄,反之亦然,當(dāng)update一條記錄時(shí),它記錄一條對(duì)應(yīng)相反的update記錄,執(zhí)行發(fā)生異常時(shí),會(huì)根據(jù)undo log中的記錄進(jìn)行回滾。undo log主要分為兩種:
- insert undo log:在insert 操作中產(chǎn)生的undo log。insert操作的記錄,只對(duì)事務(wù)本身可見,對(duì)其他事務(wù)不可見。故該undo log可以在事務(wù)提交后直接刪除,不需要進(jìn)行purge操作。
- update undo log:delete 和update操作產(chǎn)生的undo log。該undo log可能需要提供MVCC機(jī)制,因此不能在事務(wù)提交時(shí)就進(jìn)行刪除。提交時(shí)放入undo log鏈表,等待purge線程進(jìn)行最后的刪除。
對(duì)undo log有一定了解后,我們?cè)俜治鑫恼麻_頭的例子,我們以以下流程圖說明undo log保證原子性的原理:
4.2 持久性實(shí)現(xiàn)原理
InnoDB引入了Buffer Pool來優(yōu)化讀寫的性能,但是雖然Buffer Pool優(yōu)化了性能,但同時(shí)也帶來了新的問題:如果MySQL宕機(jī),而此時(shí)Buffer Pool中修改的數(shù)據(jù)還沒有刷新到磁盤,就會(huì)導(dǎo)致數(shù)據(jù)的丟失,事務(wù)的持久性無法保證。基于此,redo log就誕生了。
redo log是物理日志,記錄的是數(shù)據(jù)庫(kù)中數(shù)據(jù)庫(kù)中物理頁的情況,事務(wù)開始之后就產(chǎn)生redo log,redo log的落盤并不是隨著事務(wù)的提交才寫入的,而是在事務(wù)的執(zhí)行過程中,便開始寫入redo log文件中。
redo log包括兩部分:
- 內(nèi)存中的日志緩沖(redo log buffer),該部分日志是易失性的;
- 磁盤上的重做日志文件(redo log file),該部分日志是持久的。
在概念上,innodb通過force log at commit機(jī)制實(shí)現(xiàn)事務(wù)的持久性,即在事務(wù)提交的時(shí)候,必須先將該事務(wù)的所有事務(wù)日志寫入到磁盤上的redo log file和undo log file中進(jìn)行持久化。既然redo log也需要在事務(wù)提交時(shí)將日志寫入磁盤,為什么它比直接將Buffer Pool中修改的數(shù)據(jù)寫入磁盤(即刷臟)要快呢?主要有以下兩方面的原因:
- 刷臟是隨機(jī)IO,因?yàn)槊看涡薷牡臄?shù)據(jù)位置隨機(jī),但寫redo log是追加操作,屬于順序IO。
- 刷臟是以數(shù)據(jù)頁(Page)為單位的,MySQL默認(rèn)頁大小是16KB,一個(gè)Page上一個(gè)小修改都要整頁寫入;而redo log中只包含真正需要寫入的部分,無效IO大大減少。
我們還是以文章開頭的例子畫圖說明:
4.3 隔離性實(shí)現(xiàn)原理
隔離性是事務(wù)ACID特性里最復(fù)雜的一個(gè)。在SQL標(biāo)準(zhǔn)里定義了四種隔離級(jí)別,級(jí)別越低的隔離級(jí)別可以執(zhí)行越高的并發(fā),但同時(shí)實(shí)現(xiàn)復(fù)雜度以及開銷也越大。只要徹底理解了隔離級(jí)別以及他的實(shí)現(xiàn)原理就相當(dāng)于理解了ACID里的隔離型。前面說過原子性,隔離性,持久性的目的都是為了要做到一致性,但隔離型跟其他兩個(gè)有所區(qū)別,原子性和持久性是為了要實(shí)現(xiàn)數(shù)據(jù)的可性保障靠,比如要做到宕機(jī)后的恢復(fù),以及錯(cuò)誤后的回滾。那么隔離性是要做到什么呢?隔離性是要管理多個(gè)并發(fā)讀寫請(qǐng)求的訪問順序,這種順序包括串行或者是并行,需要說明的是寫請(qǐng)求不僅僅是指insert操作,又包括update操作。相關(guān)特性在上面已經(jīng)介紹過,大家如果不記得可以往上回看。
4.4 一致性實(shí)現(xiàn)原理
數(shù)據(jù)庫(kù)總是從一個(gè)一致性的狀態(tài)轉(zhuǎn)移到另一個(gè)一致性的狀態(tài)。主要保證了前面幾個(gè)特性,那么一致性就可以得到保證。執(zhí)行更新操作時(shí)發(fā)生異常,我們可以依據(jù)原子性進(jìn)行回滾,又或者事務(wù)提交之后,緩沖池還沒同步到磁盤的時(shí)候宕機(jī)了,這個(gè)時(shí)候可以依據(jù)持久性恢復(fù)數(shù)據(jù),有并發(fā)事務(wù)請(qǐng)求的時(shí)候依據(jù)隔離性做好事務(wù)之間的可見性問題,避免造成臟讀,不可重復(fù)讀,幻讀等。
猜你感興趣:
MYSQL專題-絕對(duì)實(shí)用的MYSQL優(yōu)化總結(jié)
MYSQL專題-使用Binlog日志恢復(fù)MySQL數(shù)據(jù)
MYSQL專題-MVCC多版本并發(fā)控制
MYSQL專題-MySQL三大日志binlog、redo log和undo log
更多文章請(qǐng)點(diǎn)擊:更多…
總結(jié)
以上是生活随笔為你收集整理的MYSQL专题-MySQL事务实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MYSQL专题-MySQL三大日志bin
- 下一篇: MYSQL专题-MVCC多版本并发控制