mysql当前时间减一分钟_MySQL数据库事务的机制【总结】
php中文網(wǎng)最新課程
每日17點(diǎn)準(zhǔn)時(shí)技術(shù)干貨分享
這幾天面試多次被問(wèn)到了數(shù)據(jù)庫(kù)事務(wù)機(jī)制、隔離級(jí)別、樂(lè)觀鎖悲觀鎖類的問(wèn)題,之前對(duì)這些只能說(shuō)有所了解,有些概念還停留在記憶層面,沒(méi)有理解,所以回答的不好。后面翻書學(xué)習(xí)了下,理解了一些東西,在此做一個(gè)記錄。
什么是事務(wù)?
事務(wù)我理解的是一個(gè)完整的業(yè)務(wù)行為,一個(gè)業(yè)務(wù)行為可能包含多個(gè)動(dòng)作,這個(gè)完整的動(dòng)作就構(gòu)成一個(gè)事務(wù)。比較經(jīng)典的例子是銀行轉(zhuǎn)賬,A賬戶轉(zhuǎn)到B賬戶,需要兩個(gè)動(dòng)作:A賬戶減,B賬戶加,必須保證這兩個(gè)動(dòng)作要么都做,要么都不做。
事務(wù)具有ACID特征,具體包括:
● 原子性(atomicity):原子性是說(shuō)事務(wù)的不可分割,要么全成功,要么全失敗,不可部分成功,部分失敗。半途失敗的情況下,需要打掃戰(zhàn)場(chǎng),也就是數(shù)據(jù)回滾。
● 一致性(consistency):一致性是說(shuō)事務(wù)的最后結(jié)果,要保證數(shù)據(jù)上沒(méi)有異常。一致性是強(qiáng)調(diào)結(jié)果,是建立在原子性上實(shí)現(xiàn)的,也就是說(shuō)能保證原子性,那就會(huì)有一致性的結(jié)果。
● 隔離性(isolation):隔離性是說(shuō)事務(wù)沒(méi)有提交前對(duì)其他事務(wù)是不可見(jiàn)的,事務(wù)間數(shù)據(jù)是隔離的(當(dāng)然不同級(jí)別隔離程度不一樣)。
● 持久性(durability): 事務(wù)提交后會(huì)持久化,可以長(zhǎng)久保存。
事務(wù)隔離級(jí)別
了解事務(wù)的隔離級(jí)別之前,需要明白數(shù)據(jù)讀取的幾個(gè)概念:
● 臟讀:就是讀到了別人還沒(méi)提交的數(shù)據(jù)。
● 可重復(fù)讀:就是同一個(gè)事物內(nèi)的兩次查詢,中間如果別人修改了查詢內(nèi)的記錄且提交了,對(duì)第二次查詢是不可見(jiàn)的,不會(huì)出現(xiàn)同條記錄兩次查詢不一致問(wèn)題。
● 幻讀:就是一個(gè)事物內(nèi)的兩次查詢,中間如果別人增加了記錄并且提交了,第二次查詢能查詢到的,會(huì)出現(xiàn)和第一次記錄不一致的現(xiàn)象。
事務(wù)的控制分很多個(gè)級(jí)別,級(jí)別的高低決定隔離的程度,MySQL中分四個(gè)級(jí)別:
● 讀未提交:這種級(jí)別是最低的,A事務(wù)的修改沒(méi)有提交對(duì)B事物是可見(jiàn)的,會(huì)出現(xiàn)數(shù)據(jù)的臟讀,一般情況下不會(huì)用到此種類型。
● 讀已提交:A事物的修改提交后才對(duì)B可見(jiàn),這種情況會(huì)出現(xiàn)數(shù)據(jù)的幻讀的問(wèn)題,兩次查詢的結(jié)果不一樣。
● 可重復(fù)讀:是MySQL默認(rèn)的級(jí)別,這種級(jí)別事物內(nèi)的兩次查詢,中間其他修改了某條記錄,對(duì)其他事務(wù)是不可見(jiàn)的,保證了重復(fù)查的情況下同條記錄的一致性,但是對(duì)于新增的情況其他事務(wù)是可見(jiàn)的,所以還是會(huì)出現(xiàn)新增幻讀的現(xiàn)象。
● 可串行化:事務(wù)之間是串行執(zhí)行的,對(duì)查詢到的每條記錄都加鎖,會(huì)出現(xiàn)阻塞的情況,并發(fā)情況下會(huì)造成嚴(yán)重的性能問(wèn)題,所以一般也不會(huì)用到這種類型。
隔離級(jí)別一覽圖
事務(wù)的隔離實(shí)現(xiàn)
事務(wù)當(dāng)中的隔離是通過(guò)兩種方式控制:一種是鎖的方式,通過(guò)時(shí)間上的挫開(kāi)達(dá)到隔離;另一種是版本控制的方式,記錄多個(gè)版本達(dá)到隔離。
1、鎖
MySQL當(dāng)中的鎖分讀鎖和寫鎖,讀鎖因?yàn)槭亲x取數(shù)據(jù)所以可以多個(gè)同時(shí)讀取同一份數(shù)據(jù),具有共享性質(zhì);寫鎖涉及到數(shù)據(jù)的變動(dòng),所以和其他寫鎖和讀鎖是相沖突的,具有排他性質(zhì)。
從鎖的粒度上分表級(jí)鎖和行級(jí)鎖,表鎖一般發(fā)生在對(duì)表結(jié)構(gòu)的修改或?qū)θ砀碌臅r(shí)候,會(huì)阻塞所有對(duì)這張表的讀寫操作;行級(jí)鎖一般發(fā)生在指定記錄更新的時(shí)候,只會(huì)鎖定指定記錄。鎖的粒度越小并發(fā)度越高,能優(yōu)先行級(jí)鎖盡量不要表鎖,和程序中鎖的粒度是一樣的原則。
2、多版本并發(fā)控制
MySQL為了性能考慮除了行級(jí)鎖以外還是另外一種方式,多版本并發(fā)控制,這中控制是由存儲(chǔ)引擎實(shí)現(xiàn)。
書中說(shuō)明了InnoDB一種簡(jiǎn)單的實(shí)現(xiàn)方式,這種方式是采用一條記錄多個(gè)版本的方式,每條記錄上增加了兩個(gè)隱藏列,一個(gè)是創(chuàng)建版本號(hào),一個(gè)是刪除版本號(hào),每開(kāi)啟一個(gè)事務(wù)都會(huì)分配一個(gè)事務(wù)版本號(hào),事務(wù)版本號(hào)是遞增的,事務(wù)內(nèi)操作都會(huì)根據(jù)這個(gè)版本號(hào)比較。
具體如下:
● 查詢時(shí):查詢當(dāng)前事務(wù)之前存在的記錄和本事務(wù)創(chuàng)建的記錄,且沒(méi)有被刪除的,即:創(chuàng)建版本號(hào)<=當(dāng)前版本號(hào) && (刪除版本號(hào)為空 || 刪除版本號(hào) > 當(dāng)前版本號(hào))
● 插入時(shí):記錄的創(chuàng)建版本號(hào)為當(dāng)前事務(wù)版本號(hào)。
● 刪除時(shí):更新記錄的刪除版本號(hào)為當(dāng)前事務(wù)版本號(hào)。
● 更新時(shí):插入一條新記錄,創(chuàng)建版本號(hào)為當(dāng)前事務(wù)版本號(hào),同時(shí)把原記錄刪除版本號(hào)改為當(dāng)前事務(wù)版本號(hào),代表已經(jīng)刪除。實(shí)際上這里的更新相當(dāng)于刪除再加一條記錄。
3、樂(lè)觀鎖和悲觀鎖
鎖從使用的角度又分悲觀鎖和樂(lè)觀鎖,悲觀鎖是持有很悲觀的態(tài)度,認(rèn)為我查到的數(shù)據(jù)都有可能被別人修改,所以查詢的時(shí)候就把這一批數(shù)據(jù)鎖起來(lái),不讓別人操作;樂(lè)觀鎖是持有很樂(lè)觀的態(tài)度,認(rèn)為我查到的數(shù)據(jù)基本不可能被別人修改,所以查詢的時(shí)候不鎖住這批數(shù)據(jù),修改提交的時(shí)候再確認(rèn)有沒(méi)有被別人修改,有種亡羊補(bǔ)牢,為時(shí)不晚的意思。
樂(lè)觀鎖和悲觀鎖的實(shí)現(xiàn):
● 悲觀鎖可以在數(shù)據(jù)庫(kù)層面很簡(jiǎn)單的解決,利用select ... for update,在查詢的時(shí)候就鎖定這部分?jǐn)?shù)據(jù)。
● 樂(lè)觀鎖的實(shí)現(xiàn)較悲觀鎖復(fù)雜,可以在數(shù)據(jù)庫(kù)在一個(gè)版本號(hào)的列,更新的時(shí)候版本號(hào)都+1,以此來(lái)確認(rèn)我查出來(lái)的數(shù)據(jù)后面有沒(méi)有別人修改,已修改的不更新或程序拋一個(gè)異常。
使用樂(lè)觀鎖還是悲觀鎖:
從性能的角度考慮樂(lè)觀鎖性能更好,在查詢到更新這段時(shí)間沒(méi)有鎖定操作,但是實(shí)現(xiàn)起來(lái)沒(méi)有悲觀鎖簡(jiǎn)單,可能出錯(cuò)。
所以要考慮的因素是系統(tǒng)的并發(fā)高不高?出現(xiàn)沖突的概率有多大?并發(fā)高的情況下選用樂(lè)觀鎖更好,反之選用悲觀鎖這種簡(jiǎn)單的方式更好。
▼
總結(jié)
以上是生活随笔為你收集整理的mysql当前时间减一分钟_MySQL数据库事务的机制【总结】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 一兆等于多少万?
- 下一篇: redis springmvc mysq