mysql怎么重復(fù)讀 mysql怎么實(shí)現(xiàn)可重復(fù)讀

mysql的重復(fù)讀如何實(shí)

lock table 讀鎖定

成都創(chuàng)新互聯(lián)公司專(zhuān)注于廬陽(yáng)網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供廬陽(yáng)營(yíng)銷(xiāo)型網(wǎng)站建設(shè),廬陽(yáng)網(wǎng)站制作、廬陽(yáng)網(wǎng)頁(yè)設(shè)計(jì)、廬陽(yáng)網(wǎng)站官網(wǎng)定制、小程序開(kāi)發(fā)服務(wù),打造廬陽(yáng)網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供廬陽(yáng)網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。

如果一個(gè)線程獲得在一個(gè)表上的read鎖,那么該線程和所有其他線程只能從表中讀數(shù)據(jù),不能進(jìn)行任何寫(xiě)操作。

lock tables user read;//讀鎖定表 unlock tables;//解鎖 lock tables user read local;//本地讀鎖定表,其他線程的insert未被阻塞,update操作被阻塞

lock table 寫(xiě)鎖定

如果一個(gè)線程在一個(gè)表上得到一個(gè) write鎖,那么只有擁有這個(gè)鎖的線程可以從表中讀取和寫(xiě)表。其它的線程被阻塞。

lock tables user write;//寫(xiě)鎖定表 unlock tables;//解鎖

Yii中的用法實(shí)例

/** * 當(dāng)日單項(xiàng)內(nèi)容狀態(tài) */ public function getPointAready($marke,$dayTime){ $model = SysRun::model()-findByAttributes(array('syr_marking'=$marke,'syr_daytime'=$dayTime)); if(empty($model)){ //表寫(xiě)鎖定 Yii::app()-db-createCommand()-setText("lock tables {{sys_run}} WRITE")-execute(); $model = new SysRun(); $model-syr_marking = $marke; $model-syr_daytime = $dayTime; $model-syr_val = 0; $model-syr_subval = 0; $model-save(); //表解鎖 Yii::app()-db-createCommand()-setText("unlock tables")-execute(); } return $model; }

更多關(guān)于Yii相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Yii框架入門(mén)及常用技巧總結(jié)》、《php優(yōu)秀開(kāi)發(fā)框架總結(jié)》、《smarty模板入門(mén)基礎(chǔ)教程》、《php操作office文檔技巧總結(jié)(包括word,excel,access,ppt)》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》

mysql可重復(fù)讀的幻讀解決方案

首先需要明確的就是“幻讀”概念: 隔離級(jí)別是可重復(fù)讀,在一個(gè)事務(wù)中前后兩次查詢,查到了其他事務(wù)insert進(jìn)來(lái)的數(shù)據(jù)。

強(qiáng)調(diào)的是讀取到了其他事務(wù)插入進(jìn)來(lái)的數(shù)據(jù)。

下面來(lái)論證一下可重復(fù)讀下幻讀的解決方案

先明確一下,for update語(yǔ)法就是當(dāng)前讀,也就是查詢當(dāng)前已經(jīng)提交的數(shù)據(jù),并且是帶悲觀鎖的。沒(méi)有for update就是快照讀,也就是根據(jù)readView讀取的undolog中的數(shù)據(jù)。

如果按照以上猜想,那么整個(gè)執(zhí)行結(jié)果就違背了 可重復(fù)讀 的隔離級(jí)別了。

那么我們?cè)偌僭O(shè)select * from TABLE where d = 5 for update;這條語(yǔ)句鎖定的是所有被掃描到的數(shù)據(jù)。

這是因?yàn)門(mén)2階段的update會(huì)被阻塞住,畢竟所有被掃描到的記錄都被鎖定了。

按照上述推理過(guò)程,很顯然,即使鎖定所有掃描到的數(shù)據(jù)行,也依然存在幻讀的情況。違背了 可重復(fù)讀 的隔離級(jí)別。

針對(duì)這個(gè)情況,我們要解決幻讀的問(wèn)題,那么就要求針對(duì)所有被掃描的記錄行以及還不存在的d=5的記錄行都給鎖住。

至此,當(dāng)前查詢結(jié)果完全滿足 可重復(fù)讀 的隔離級(jí)別。

通過(guò)以上推論,我們可以總結(jié)一下,在可重復(fù)讀的隔離級(jí)別下,解決幻讀除了需要鎖定所有掃描到的記錄行外,還需要鎖定行之間的間隙,也就是通過(guò)間隙鎖來(lái)解決幻讀的問(wèn)題。

mysql是如何實(shí)現(xiàn)可重復(fù)讀的?

一個(gè)事務(wù)要更新一行,如果剛好有另外一個(gè)事務(wù)擁有這一行的行鎖,會(huì)被鎖住,進(jìn)入等待狀態(tài)。既然進(jìn)入了等待狀態(tài),那么等到這個(gè)事務(wù)自己獲取到行鎖要更新數(shù)據(jù)的時(shí)候,它讀到的值又是什么呢?

可重復(fù)讀隔離級(jí)別下,事務(wù)在啟動(dòng)的時(shí)候就“拍了個(gè)整個(gè)庫(kù)的快照”。如果一個(gè)庫(kù)有100G,那么我啟動(dòng)一個(gè)事務(wù),MySQL就要拷?100G的數(shù)據(jù)出來(lái),這個(gè)過(guò)程得多慢啊。但是平時(shí)事務(wù)執(zhí)行起來(lái)卻是非??斓?。不是全部拷貝出來(lái)那是怎么實(shí)現(xiàn)的呢?

InnoDB里面每個(gè)事務(wù)有一個(gè)唯一的事務(wù)ID,叫作transaction id。它是在事務(wù)開(kāi)始的時(shí)候向InnoDB的事務(wù)系統(tǒng)申請(qǐng)的,是按申請(qǐng)順序嚴(yán)格遞增的。

而每行數(shù)據(jù)也都是有多個(gè)版本的。每次事務(wù)更新數(shù)據(jù)的時(shí)候,都會(huì)生成一個(gè)新的數(shù)據(jù)版本,并且把transaction id賦值給這個(gè)數(shù) 據(jù)版本的事務(wù)ID,記為row trx_id。同時(shí),舊的數(shù)據(jù)版本要保留,并且在新的數(shù)據(jù)版本中,能夠有信息可以直接拿到它。

數(shù)據(jù)表中的一行記錄,其實(shí)可能有多個(gè)版本(row),每個(gè)版本有自己的row trx_id。

圖中虛線框里是同一行數(shù)據(jù)的4個(gè)版本,當(dāng)前最新版本是V4,k的值是22,它是被transaction id 為25的事務(wù)更新的,因此它的row trx_id也是25。語(yǔ)句更新會(huì)生成undo log(回滾日志),圖中的三個(gè)虛線箭頭,就是undo log。

按照可重復(fù)讀的定義,一個(gè)事務(wù)啟動(dòng)的時(shí)候,能夠看到所有已經(jīng)提交的事務(wù)結(jié)果。但是之后,這個(gè)事務(wù)執(zhí)行期間,其他事務(wù)的更新對(duì)它不可?。

一個(gè)事務(wù)只需要在啟動(dòng)的時(shí)候聲明說(shuō),“以我啟動(dòng)的時(shí)刻為準(zhǔn),如果一個(gè)數(shù)據(jù)版本是在我啟動(dòng)之前生成的,就認(rèn);如果是我啟動(dòng)以后才生成的,我就不認(rèn),我必須要找到它的上一個(gè)版本”。

如果“上一個(gè)版本”也不可?,那就得繼續(xù)往前找。如果是這個(gè)事務(wù)自己更新的數(shù)據(jù),它自己還是要認(rèn)的。

在實(shí)現(xiàn)上, InnoDB為每個(gè)事務(wù)構(gòu)造了一個(gè)數(shù)組,用來(lái)保存這個(gè)事務(wù)啟動(dòng)瞬間,當(dāng)前正在“活躍”的所有事務(wù)ID?!盎钴S”指的就 是,啟動(dòng)了但還沒(méi)提交。數(shù)組里面事務(wù)ID的最小值記為低水位,當(dāng)前系統(tǒng)里面已經(jīng)創(chuàng)建過(guò)的事務(wù)ID的最大值加1記為高水位。 這個(gè)視圖數(shù)組和高水位,就組成了當(dāng)前事務(wù)的一致性視圖(read-view)。而數(shù)據(jù)版本的可?性規(guī)則,就是基于數(shù)據(jù)的row trx_id和這個(gè)一致性視圖的對(duì)比結(jié)果得到的。

InnoDB利用了“所有數(shù)據(jù)都有多個(gè)版本”的這個(gè)特性,實(shí)現(xiàn)了“秒級(jí)創(chuàng)建快照”的能力。

回到我們最開(kāi)始的表格,看看最后執(zhí)行的結(jié)果是多少。做如下假設(shè):

事務(wù)A的視圖數(shù)組就是[99,100], 事務(wù)B的視圖數(shù)組是[99,100,101], 事務(wù)C的視圖數(shù)組是[99,100,101,102]。為了簡(jiǎn)化分析,我先把其他干擾語(yǔ)句去掉,只畫(huà)出跟事務(wù)A查詢邏輯有關(guān)的操作:

第一個(gè)有效更新是事務(wù)C,把數(shù)據(jù)從(1,1)改成了(1,2)。這時(shí)候,這個(gè)數(shù)據(jù)的最新版本的row trx_id是102,而90這個(gè)版本已經(jīng)成為了歷史版本。 第二個(gè)有效更新是事務(wù)B,把數(shù)據(jù)從(1,2)改成了(1,3)。這時(shí)候,這個(gè)數(shù)據(jù)的最新版本(即row trx_id)是101,而102又成為了歷史版本。

事務(wù)B的update語(yǔ)句,如果按照一致性讀,好像結(jié)果不對(duì)哦?

事務(wù)B的視圖數(shù)組是先生成的,之后事務(wù)C才提交,不是應(yīng)該看不?(1,2)嗎,怎么能算出(1,3)來(lái)?

事務(wù)B在更新之前查詢一次數(shù)據(jù),這個(gè)查詢返回的k的值確實(shí)是1。 但是,當(dāng)它要去更新數(shù)據(jù)的時(shí)候,就不能再在歷史版本上更新了,否則事務(wù)C的更新就丟失了。因此,事務(wù)B此時(shí)的set k=k+1是在(1,2)的基礎(chǔ)上進(jìn)行的操作。 所以,這里就用到了這樣一條規(guī)則:更新數(shù)據(jù)都是先讀后寫(xiě)的,而這個(gè)讀,只能讀當(dāng)前的值,稱(chēng)為 “當(dāng)前讀” ( current read )。

在更新的時(shí)候,當(dāng)前讀拿到的數(shù)據(jù)是(1,2),更新后生成了新版本的數(shù)據(jù)(1,3),這個(gè)新版本的row trx_id是101。

所以,在執(zhí)行事務(wù)B查詢語(yǔ)句的時(shí)候,一看自己的版本號(hào)是101,最新數(shù)據(jù)的版本號(hào)也是101,是自己的更新,可以直接使用, 所以查詢得到的k的值是3。

select語(yǔ)句如果加鎖,也是當(dāng)前讀。

如果把事務(wù)A的查詢語(yǔ)句select * from t where id=1修改一下,加上lock in share mode 或 for update,也都可以讀到版本號(hào)是101的數(shù)據(jù),返回的k的值是3。下面這兩個(gè)select語(yǔ)句,就是分別加了讀鎖(S鎖,共享鎖)和寫(xiě)鎖(X鎖,排他鎖)。

事務(wù)C’的不同是,更新后并沒(méi)有?上提交,在它提交前,事務(wù)B的更新語(yǔ)句先發(fā)起了。前面說(shuō)過(guò)了,雖然事務(wù)C’還沒(méi)提交,但是(1,2)這個(gè)版本也已經(jīng)生成了,并且是當(dāng)前的最新版本。那么,事務(wù)B的更新語(yǔ)句會(huì)怎么處理呢?

兩階段鎖協(xié)議,事務(wù)C’沒(méi)提交,也就是說(shuō)(1,2)這個(gè)版本上的寫(xiě)鎖還沒(méi)釋放。 而事務(wù)B是當(dāng)前讀,必須要讀最新版本,而且必須加鎖,因此就被鎖住了,必須等到事務(wù)C’釋放這個(gè)鎖,才能繼續(xù)它的當(dāng)前讀。

回到最初的問(wèn)題,事務(wù)的可重復(fù)讀的能力是怎么實(shí)現(xiàn)的?

本文題目:mysql怎么重復(fù)讀 mysql怎么實(shí)現(xiàn)可重復(fù)讀
分享路徑:http://muchs.cn/article14/dohcjge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)云服務(wù)器、ChatGPT、網(wǎng)站制作、品牌網(wǎng)站建設(shè)

廣告

聲明:本網(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)

網(wǎng)站優(yōu)化排名