MySQL數(shù)據(jù)庫事務的機制是什么?這幾天很面試者都被問到了數(shù)據(jù)庫事務機制、隔離級別、樂觀鎖悲觀鎖類的問題,之前對這些只能說有所了解,但并不是特別深刻,今天小編就給大家總結(jié)了一下有關(guān)的概念。
創(chuàng)新互聯(lián)于2013年開始,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務公司,擁有項目成都做網(wǎng)站、網(wǎng)站制作網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元通川做網(wǎng)站,已為上家服務,為通川各地企業(yè)和個人服務,聯(lián)系電話:028-86922220
一、什么是事務?
事務我理解的是一個完整的業(yè)務行為,一個業(yè)務行為可能包含多個動作,這個完整的動作就構(gòu)成一個事務。比較經(jīng)典的例子是銀行轉(zhuǎn)賬,A賬戶轉(zhuǎn)到B賬戶,需要兩個動作:A賬戶減,B賬戶加,必須保證這兩個動作要么都做,要么都不做。
事務具有ACID特征,具體包括:
● 原子性(atomicity):原子性是說事務的不可分割,要么全成功,要么全失敗,不可部分成功,部分失敗。半途失敗的情況下,需要打掃戰(zhàn)場,也就是數(shù)據(jù)回滾。
● 一致性(consistency):一致性是說事務的最后結(jié)果,要保證數(shù)據(jù)上沒有異常。一致性是強調(diào)結(jié)果,是建立在原子性上實現(xiàn)的,也就是說能保證原子性,那就會有一致性的結(jié)果。
● 隔離性(isolation):隔離性是說事務沒有提交前對其他事務是不可見的,事務間數(shù)據(jù)是隔離的(當然不同級別隔離程度不一樣)。
● 持久性(durability): 事務提交后會持久化,可以長久保存。
二、事務隔離級別
了解事務的隔離級別之前,需要明白數(shù)據(jù)讀取的幾個概念:
● 臟讀:就是讀到了別人還沒提交的數(shù)據(jù)。
● 可重復讀:就是同一個事物內(nèi)的兩次查詢,中間如果別人修改了查詢內(nèi)的記錄且提交了,對第二次查詢是不可見的,不會出現(xiàn)同條記錄兩次查詢不一致問題。
● 幻讀:就是一個事物內(nèi)的兩次查詢,中間如果別人增加了記錄并且提交了,第二次查詢能查詢到的,會出現(xiàn)和第一次記錄不一致的現(xiàn)象。
事務的控制分很多個級別,級別的高低決定隔離的程度,MySQL中分四個級別:
● 讀未提交:這種級別是最低的,A事務的修改沒有提交對B事物是可見的,會出現(xiàn)數(shù)據(jù)的臟讀,一般情況下不會用到此種類型。
● 讀已提交:A事物的修改提交后才對B可見,這種情況會出現(xiàn)數(shù)據(jù)的幻讀的問題,兩次查詢的結(jié)果不一樣。
● 可重復讀:是MySQL默認的級別,這種級別事物內(nèi)的兩次查詢,中間其他修改了某條記錄,對其他事務是不可見的,保證了重復查的情況下同條記錄的一致性,但是對于新增的情況其他事務是可見的,所以還是會出現(xiàn)新增幻讀的現(xiàn)象。
● 可串行化:事務之間是串行執(zhí)行的,對查詢到的每條記錄都加鎖,會出現(xiàn)阻塞的情況,并發(fā)情況下會造成嚴重的性能問題,所以一般也不會用到這種類型。
隔離級別一覽圖
三、事務的隔離實現(xiàn)
事務當中的隔離是通過兩種方式控制:一種是鎖的方式,通過時間上的挫開達到隔離;另一種是版本控制的方式,記錄多個版本達到隔離。
1、鎖
MySQL當中的鎖分讀鎖和寫鎖,讀鎖因為是讀取數(shù)據(jù)所以可以多個同時讀取同一份數(shù)據(jù),具有共享性質(zhì);寫鎖涉及到數(shù)據(jù)的變動,所以和其他寫鎖和讀鎖是相沖突的,具有排他性質(zhì)。
從鎖的粒度上分表級鎖和行級鎖,表鎖一般發(fā)生在對表結(jié)構(gòu)的修改或?qū)θ砀碌臅r候,會阻塞所有對這張表的讀寫操作;行級鎖一般發(fā)生在指定記錄更新的時候,只會鎖定指定記錄。鎖的粒度越小并發(fā)度越高,能優(yōu)先行級鎖盡量不要表鎖,和程序中鎖的粒度是一樣的原則。
2、多版本并發(fā)控制
MySQL為了性能考慮除了行級鎖以外還是另外一種方式,多版本并發(fā)控制,這中控制是由存儲引擎實現(xiàn)。
書中說明了InnoDB一種簡單的實現(xiàn)方式,這種方式是采用一條記錄多個版本的方式,每條記錄上增加了兩個隱藏列,一個是創(chuàng)建版本號,一個是刪除版本號,每開啟一個事務都會分配一個事務版本號,事務版本號是遞增的,事務內(nèi)操作都會根據(jù)這個版本號比較。具體如下:
● 查詢時:查詢當前事務之前存在的記錄和本事務創(chuàng)建的記錄,且沒有被刪除的,即:創(chuàng)建版本號<=當前版本號 && (刪除版本號為空 || 刪除版本號 > 當前版本號)
● 插入時:記錄的創(chuàng)建版本號為當前事務版本號。
● 刪除時:更新記錄的刪除版本號為當前事務版本號。
● 更新時:插入一條新記錄,創(chuàng)建版本號為當前事務版本號,同時把原記錄刪除版本號改為當前事務版本號,代表已經(jīng)刪除。實際上這里的更新相當于刪除再加一條記錄。
3、樂觀鎖和悲觀鎖
鎖從使用的角度又分悲觀鎖和樂觀鎖,悲觀鎖是持有很悲觀的態(tài)度,認為我查到的數(shù)據(jù)都有可能被別人修改,所以查詢的時候就把這一批數(shù)據(jù)鎖起來,不讓別人操作;樂觀鎖是持有很樂觀的態(tài)度,認為我查到的數(shù)據(jù)基本不可能被別人修改,所以查詢的時候不鎖住這批數(shù)據(jù),修改提交的時候再確認有沒有被別人修改,有種亡羊補牢,為時不晚的意思。
四、樂觀鎖和悲觀鎖的實現(xiàn):
● 悲觀鎖可以在數(shù)據(jù)庫層面很簡單的解決,利用select ... for update,在查詢的時候就鎖定這部分數(shù)據(jù)。
● 樂觀鎖的實現(xiàn)較悲觀鎖復雜,可以在數(shù)據(jù)庫在一個版本號的列,更新的時候版本號都+1,以此來確認我查出來的數(shù)據(jù)后面有沒有別人修改,已修改的不更新或程序拋一個異常。
使用樂觀鎖還是悲觀鎖:
從性能的角度考慮樂觀鎖性能更好,在查詢到更新這段時間沒有鎖定操作,但是實現(xiàn)起來沒有悲觀鎖簡單,可能出錯。所以要考慮的因素是系統(tǒng)的并發(fā)高不高?出現(xiàn)沖突的概率有多大?并發(fā)高的情況下選用樂觀鎖更好,反之選用悲觀鎖這種簡單的方式更好。
看完上文,MySQL數(shù)據(jù)庫事務的機制是什么這個問題應該很好解答了吧?感覺拿出你的小本本記下來吧。