国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

臟讀、幻讀,要想搞懂不容易!

數(shù)據(jù)庫 MySQL
臟讀、幻讀、不可重復(fù)讀、當(dāng)前讀、快照讀,這些名詞經(jīng)常搞的讓人頭暈。因為一般人大腦的主線就是單線程的,并不能一次性處理多個事務(wù)。

[[394503]]

本文轉(zhuǎn)載自微信公眾號「小姐姐味道」,作者小姐姐養(yǎng)的狗02號。轉(zhuǎn)載本文請聯(lián)系小姐姐味道公眾號。   

臟讀、幻讀、不可重復(fù)讀、當(dāng)前讀、快照讀,這些名詞經(jīng)常搞的讓人頭暈。因為一般人大腦的主線就是單線程的,并不能一次性處理多個事務(wù)。

要想記憶深刻,我們得借助幾個實例。讀完本文,你一定會豁然開朗,忍不住三連走起。

但在這之前,我們需要看一下當(dāng)前的數(shù)據(jù)庫隔離級別,到底是什么。比如MySQL。

  1. select @@tx_isolation; 

MySQL就包含4種隔離級別,隔離的當(dāng)然是數(shù)據(jù)。要修改隔離級別的話,可以使用下面的SQL語句。

  1. set session transaction isolation level read uncommitted
  2. set session transaction isolation level read committed
  3. set session transaction isolation level repeatable read
  4. set session transaction isolation level serializable

ok,我們創(chuàng)建一張小小的測試表,來看一下并發(fā)環(huán)境下的魔幻效果。

  1. CREATE TABLE `xjjdog_tx` ( 
  2.  `id` INT(11) NOT NULL
  3.  `nameVARCHAR(50) NOT NULL COLLATE 'utf8_general_ci'
  4.  `money` BIGINT(20) NOT NULL DEFAULT '0'
  5.  PRIMARY KEY (`id`) USING BTREE 
  6. COLLATE='utf8_general_ci' 
  7. ENGINE=InnoDB 
  8. INSERT INTO `xjjdog_tx` (`id`, `name`, `money`) VALUES (2, 'xjjdog1', 100); 
  9. INSERT INTO `xjjdog_tx` (`id`, `name`, `money`) VALUES (1, 'xjjdog0', 100); 

1. 臟讀

臟讀,意思就是讀出了臟數(shù)據(jù)。啥叫臟數(shù)據(jù)?就是另外一個事務(wù)還沒有提交的數(shù)據(jù)。在read uncommitted隔離級別下,就會出現(xiàn)臟讀。比如下面這個時序

  1. 事務(wù) A:set session transaction isolation level read uncommitted
  2. 事務(wù) B:set session transaction isolation level read uncommitted
  3. 事務(wù) A:START TRANSACTION ; 
  4. 事務(wù) B:START TRANSACTION ; 
  5. 事務(wù) A:UPDATE xjjdog_tx SET money=money+100 WHERE NAME='xjjdog0'
  6. 事務(wù) B:UPDATE xjjdog_tx SET money=money+100 WHERE NAME='xjjdog0'
  7. 事務(wù) A:ROLLBACK ; 
  8. 事務(wù) B:COMMIT ; 
  9. 事務(wù) B:SELECT * FROM xjjdog_tx ; 

在這個場景下,money的原始值為100,分別在兩個session中進(jìn)行了加100的操作,然后回滾了其中的一個session事務(wù)。結(jié)果,經(jīng)過查詢,發(fā)現(xiàn)money的值保持100不變。也就是其中一次加100的操作被覆蓋掉了。

所以臟讀發(fā)生有幾個條件。

  • 高并發(fā)場景,在一個事務(wù)A開始之后還沒結(jié)束之前,有另外一個事務(wù)參與了事務(wù)A所涉及的數(shù)據(jù)行讀寫
  • 事務(wù)隔離級別處于最低的讀未提交
  • 在你使用到這些數(shù)據(jù)之后,事務(wù)A回滾,造成你之前拿到的數(shù)據(jù)已經(jīng)不再存在

解決方式,只需要設(shè)置成隔離級別比read uncommitted高即可。

2. 不可重復(fù)讀

把隔離級別設(shè)置成read committed即可避免臟讀,這其實非常好理解。臟讀產(chǎn)生的根本原因就是在事務(wù)的執(zhí)行期間有別的操作亂入,這個隔離級別要求事務(wù)A提交之后,修改后的值,才能被事務(wù)B讀到,所以臟讀是不可能會發(fā)生的,從根本上杜絕了。

但read commited會發(fā)生不可重復(fù)讀的情況。

顧名思義,就是在一個事務(wù)周期內(nèi),對于一個值的讀取,產(chǎn)生了兩個結(jié)果。

不可重復(fù)讀,證明了世界并不是總圍繞著你轉(zhuǎn)的。在你的事務(wù)執(zhí)行期間,會有無數(shù)的其他事務(wù)執(zhí)行,如果你的事務(wù)持續(xù)時間超過了這些事務(wù),那么你就可能讀到兩個或者更多的值。

讓我來給你講一個故事。

從前,有一顆桃樹,長了12棵桃子。有一只猴子,叫做xjjdog,它想吃上面的桃子,但桃子還不熟。

第二天去看的時候,它發(fā)現(xiàn)桃子少了一個,變成了11個,經(jīng)過仔細(xì)打聽,原來是被猴子A搶先吃掉一個。

第二天去看的時候,桃子又少了一個,變成了10個,原來是被饞嘴的猴子B吃掉一個。

如此這般,桃子一天天少了下去,只剩下最后的2個了,但桃子還是沒熟。

再不摘桃子就沒了,xjjdog摘下了最后的2個桃子,正打算大快朵頤,結(jié)果跳出一只猴子X,說我盯著這些桃子已經(jīng)1年了...

在這故事中,猴子A、B的事務(wù)持續(xù)周期是1天;xjjdog的事務(wù)持續(xù)周期是直到桃子成熟;猴子X的持續(xù)周期更長,可能是一年。它們每天看到的桃子,并不總是12個。今天的桃子,可能被其他的猴子(事務(wù))給吃掉了,造成了觀測的結(jié)果是不一樣的,這就是不可重復(fù)讀的概念。

有時候,即使讀到的值是一樣的,也不能證明沒問題。比如有財務(wù)挪用了2億去炒股,然后在月底把2億還了回來,雖然最終的金額都是一致的,但由于你的對賬周期長,就發(fā)現(xiàn)不了這種差異。

如何解決不可重復(fù)讀呢?先要看一下不可重復(fù)讀是不是問題。

有的系統(tǒng),要求的就是這樣的邏輯,每次在事務(wù)中讀取到不一樣的值,它是可以忍受的。但如果你想要在桃子成熟之前,桃子的數(shù)量都在你的掌控之中,那不可重復(fù)讀就是一種問題。

一種非常好的方式,就是xjjdog一直站在桃樹地下。當(dāng)有別的猴子想要摘桃,就把它趕走。這種方式可行,但在數(shù)據(jù)庫中非常低效,這是serializable級別的做法。

MySQL有一個默認(rèn)的事務(wù)隔離級別,叫做repeatable read,使用了MVCC的方式(innodb),要更輕量級一些。

3. 可重復(fù)讀

這就是MVCC(Multi-Version Concurrency Control)的功勞了,它有三個特點(diǎn)。

每行數(shù)據(jù)都存在一個版本,每次數(shù)據(jù)更新時都更新該版本

修改時,拷貝一份,當(dāng)前版本隨意修改,事務(wù)之間無干擾

保存時比較版本號,如果成功commit覆蓋原記錄,失敗則rollback

MVCC在InnoDB中的實現(xiàn)主要是為了提高數(shù)據(jù)庫并發(fā)性能,用更好的方式去處理讀-寫沖突,做到即使有讀寫沖突時,也能做到不加鎖,非阻塞并發(fā)讀。它的實現(xiàn)關(guān)鍵也有三項技術(shù):

  1. 3個隱式字段:DB_TRX_ID,最近修改它的事務(wù)ID;DB_ROLL_PTR,回滾指針,指向上一個版本;DB_ROW_ID,隱藏主鍵
  2. undo日志:的對同一記錄的修改,會生成針對此記錄的版本變更鏈表
  3. read view:快照讀操作的時候,產(chǎn)生的讀視圖。除了使用上面的額外信息,它也會維護(hù)一個活躍的事務(wù)ID集合

一切的關(guān)鍵,就在于快照這兩個字上面。

比如事務(wù)A對某個記錄進(jìn)行了快照讀,那么在快照讀的這一刻,就生成了一個Read View。在這一刻,事務(wù)B和C,還沒有commit,事務(wù)D和E,在建立ReadView那一刻之前,commit完成,那么這個Read View,就不能夠讀到B和C的修改。

但可惜的是,可重復(fù)讀,只能解決快照讀的不可重復(fù)讀,快照讀的時機(jī),也會影響讀取的準(zhǔn)確程度。請看下面兩種情況。

下面這種情況讀到的是500。

事務(wù)A 事務(wù)B
開啟事務(wù) 開啟事務(wù)
快照讀(無影響)查詢金額為500 快照讀查詢金額為500
更新金額為400  
提交事務(wù)  
  select 快照讀金額為500
  select lock in share mode當(dāng)前讀金額為400

下面這種情況讀到的是400。

事務(wù)A 事務(wù)B
開啟事務(wù) 開啟事務(wù)
快照讀(無影響)查詢金額為500  
更新金額為400  
提交事務(wù)  
  select 快照讀金額為400
  select lock in share mode當(dāng)前讀金額為400
 

(表格來自[SnailMann]的博客)。

4. 幻讀

幻讀,這個詞本身就非常的迷幻。在RU、RC、RR級別下,都會出現(xiàn)幻讀。

拿一個最簡單的例子來說。讓你select一條記錄是否存在然后打算進(jìn)行后續(xù)插入時,如果這條記錄不存在,然后你執(zhí)行了插入操作,但在實際執(zhí)行插入操作的時候,結(jié)果卻報錯了,這條記錄已經(jīng)存在了,這就是幻讀。

首先,確認(rèn)目前時可重復(fù)讀級別。如果不是,則修改之。

  1. SELECT @@tx_isolation 
  2. set session transaction isolation level repeatable read 

讓我們來看一下這個靈異過程。

有5個步驟,我都給你標(biāo)好了。下面一一介紹。

  1. 事務(wù)A使用begin開啟一個事務(wù),然后查詢id為3的記錄,此時不存在。但由于快照讀開啟了一個針對于id為3的記錄的read view,所以在這個事務(wù)自始至終都不能夠讀到為3的記錄。很好,這就是我們不可重復(fù)讀所需要的
  2. 接下來,事務(wù)B插入了一條id為3的記錄,并提交成功
  3. 事務(wù)A此時也想插入這條記錄,于是執(zhí)行了相同的插入操作,結(jié)果數(shù)據(jù)庫報錯,顯示這條記錄已經(jīng)存在
  4. 事務(wù)A此時一臉懵逼,想看一下這條記錄到底是啥,但當(dāng)它再次執(zhí)行select語句的時候,卻查不到這條記錄
  5. 但在其他事務(wù)中,是可以看到這條記錄的,因為它已經(jīng)正確提交

這就是幻讀。

5. 如何解決幻讀

幻讀有錯么?多數(shù)情況下沒錯,就是報錯怪異了些。要防止幻讀,需要開啟FOR UPDATE這樣高強(qiáng)度的鎖定,實際情況是非常少用。

為什么上面的操作,insert能報錯,但select卻無法查到數(shù)據(jù)呢?這就不得不提一下數(shù)據(jù)庫讀的兩種模式:

快照讀:普通的select操作,是從read view中讀取數(shù)據(jù),讀取的可能是歷史數(shù)據(jù)

當(dāng)前讀:insert、update、delete、select..for update這種操作,讀取的總是當(dāng)前的最新數(shù)據(jù)

對于當(dāng)前讀,你讀取的行,以及行的間隙都會被加鎖,直到事務(wù)提交時才會釋放,其他的事務(wù)無法進(jìn)行修改,所以也不會出現(xiàn)不可重復(fù)讀、幻讀的情形。所以insert能夠發(fā)現(xiàn)沖突,而普通select卻不可以。要想解決幻讀,就需要加X鎖。在上面這種情況,就可以在事務(wù)A中執(zhí)行:

  1. SELECT * FROM xjjdog_tx WHERE id=3 FOR UPDATE 

當(dāng)這么做的時候,即使id為3的記錄不存在,它也會創(chuàng)建鎖(在背后可能根據(jù)記錄的存在與否加行X鎖或者next-key lock間隙x鎖)。

6. 總結(jié)

下面簡單總結(jié)一下。

臟讀,就是一個事務(wù)讀取到另一個事務(wù)還沒有提交的記錄。當(dāng)其他事務(wù)發(fā)生回滾的時候,就會出現(xiàn)問題。

不可重復(fù)讀,意思是在同一個事務(wù)里,讀多次可能會獲得不一致的結(jié)果。這是因為在事務(wù)執(zhí)行期間,有別的事務(wù)修改了這些記錄。

MySQL默認(rèn)是可重復(fù)讀,但會發(fā)生幻讀的情況。幻讀是由于快照讀和當(dāng)前讀的差別產(chǎn)生的。

要想解決幻讀,就需要加鎖(X鎖,Gap鎖等),比如for update,全部改成當(dāng)前讀直到事務(wù)結(jié)束,自然沒有問題。

所謂的最高級別serializable,不過是全部搞成了當(dāng)前讀而已,在高并發(fā)的環(huán)境下效率,可想而知。所以幾乎沒有用的。

作者簡介:小姐姐味道 (xjjdog),一個不允許程序員走彎路的公眾號。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。我的個人微信xjjdog0,歡迎添加好友,進(jìn)一步交流。

 

責(zé)任編輯:武曉燕 來源: 小姐姐味道
相關(guān)推薦

2022-01-03 07:18:05

臟讀幻讀 MySQL

2024-04-19 08:18:47

MySQLSQL隔離

2022-04-27 07:32:02

臟讀幻讀不可重復(fù)讀

2019-03-21 09:06:00

數(shù)據(jù)庫復(fù)讀幻讀

2024-04-24 08:26:35

事務(wù)數(shù)據(jù)InnoDB

2020-06-09 08:19:25

微服務(wù)網(wǎng)站架構(gòu)

2023-11-01 14:13:00

MySQL事務(wù)隔離級別

2023-08-09 17:22:30

MVCCMySQL數(shù)據(jù)

2012-06-13 14:58:09

BYOD移動辦公

2020-06-18 10:52:17

運(yùn)維架構(gòu)技術(shù)

2013-09-22 09:16:25

碼農(nóng)程序員黑客

2018-01-24 07:28:20

2017-04-27 13:30:14

AndroidWebView移動應(yīng)用

2009-09-04 08:19:24

Windows 7優(yōu)缺點(diǎn)

2009-02-12 17:25:21

Windows7試用下載

2025-02-26 10:40:44

數(shù)據(jù)庫并發(fā)幻讀

2023-08-31 22:17:15

JavaMySQLB+樹

2011-12-16 14:52:55

移動互聯(lián)聯(lián)想

2022-06-30 08:00:00

MySQL關(guān)系數(shù)據(jù)庫開發(fā)

2024-09-02 00:00:00

MySQL幻讀數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

高清shemale亚洲人妖| 欧美mv日韩mv亚洲| 亚洲国产精品日韩| 一区二区激情| 91精品综合久久| 成人毛片在线| 国产精品久久久久久久久久久久| 婷婷激情成人| 亚洲人成电影网站色| 91超碰在线播放| 精品va天堂亚洲国产| 黄色av电影在线播放| 欧美亚洲综合另类| 国产中文在线| 欧美又粗又大又爽| 国产高清av在线| 欧美性三三影院| 91社区在线观看播放| 欧美日韩久久一区二区| 4438x成人网全国最大| 欧美成人女星排名| 老色鬼在线视频| 国产一区二区三区直播精品电影| 精品欧美一区二区三区在线观看 | 亚洲精品中文字幕乱码三区| 日本免费观看网站| 国产精品女同一区二区三区| 成人伊人222| 亚洲一区精品在线| 裸体xxxx视频在线| 欧美一区二区三区在线视频 | 色国产精品一区在线观看| 黄色网址在线播放| 777色狠狠一区二区三区| 怡红院av在线| 亚洲偷熟乱区亚洲香蕉av| 成人免费91| 国产不卡一区二区在线播放| 欧美gay男男猛男无套| 国产精品一区二区a| 日韩精品亚洲一区二区三区免费| 一区二区三区不卡在线| 91年精品国产| 激情婷婷丁香| 欧美日本一区二区| 欧美亚洲日本精品| 欧美精品激情blacked18| 日韩中文欧美| 精品免费视频123区| 国产成a人亚洲| 丁香激情视频| 91精品国产综合久久福利 | 久草精品视频| 成人免费淫片aa视频免费| 国产日韩欧美一区| 国产自产在线视频| 亚洲一区二区偷拍精品| 中文av资源在线| 欧美巨猛xxxx猛交黑人97人| 久久久久久久久99精品大| 欧美精品一区在线| 久久精品视频免费| 成人影视在线播放| 在线日韩av观看| av中字幕久久| 日韩精彩视频| 中文字幕乱码日本亚洲一区二区| 欧美成熟毛茸茸| 日韩av最新在线观看| 欧美男人操女人视频| 久久本道综合色狠狠五月| 久久综合色婷婷| 成人在线免费视频| 久久精品男人天堂| 亚洲高清在线| 另类图片亚洲色图| 精品黑人一区二区三区久久| 加勒比久久高清| 亚洲bbw性色大片| 自拍av一区二区三区| 国产黄色大片在线观看| 欧美资源在线观看| 狠狠色综合色综合网络| 在线看片线路1| 久久亚洲精品网站| 天堂va蜜桃一区二区三区 | 国产精品专区第二| 老司机午夜精品99久久| 久久白虎精品| 久热精品在线视频| 视频一区视频二区中文| 在线视频xx| 国产视频丨精品|在线观看| 91精品国产91久久久久久密臀 | 久久久久久久激情视频| 老妇喷水一区二区三区| 亚洲精品少妇久久久久久| 中文字幕精品www乱入免费视频| 黑人一区二区| 国产超碰在线| 欧美激情喷水视频| 国产精品77777竹菊影视小说| www在线播放| 青青草一区二区| 91视频免费观看| 天堂网在线最新版www中文网| 动漫一区二区在线| 韩曰欧美视频免费观看| 国产欧美一区二区三区精品观看| 无码aⅴ精品一区二区三区浪潮 | 精品在线一区二区| 在线免费观看的av网站| 成人精品福利视频| 亚洲久草在线视频| 一区二区在线视频观看| 成人在线免费观看av| 亚洲精品视频在线观看视频| 久久精品亚洲一区二区| 888av在线| 国产精品二区三区四区| 精品人伦一区二区三区蜜桃免费| 日韩激情啪啪| 国产福利电影在线观看| 91高清免费视频| 亚洲欧洲日韩女同| 欧美男人操女人视频| 自拍偷拍一区二区三区四区| 日韩中文理论片| 91视频一区二区三区| 亚洲男人在线| 国产乱子伦农村叉叉叉| 日韩日本欧美亚洲| 91在线国内视频| 欧美h版在线观看| 男人亚洲天堂网| 国内精品视频一区| 中文字幕亚洲一区二区av在线| 久久男人av| 国内精品卡一卡二卡三新区| 国产噜噜噜噜久久久久久久久| 亚洲高清在线视频| 一区二区三区网站| 男人的天堂在线视频免费观看| 麻豆亚洲一区| 亚洲精品少妇网址| 26uuu亚洲综合色| 日韩av午夜| 在线看片你懂的| 久久精品一二三区| 亚洲黄色av女优在线观看 | 国产精品**亚洲精品| 亚洲性生活网站| 国产成人avxxxxx在线看| 欧美日韩精品在线| 欧美日韩国产成人精品| 亚洲奶水xxxx哺乳期| 国产奶头好大揉着好爽视频| 宅男66日本亚洲欧美视频| 久久久精品一品道一区| 蜜桃一区二区三区| 国产小视频在线| 亚洲国产精品毛片| 久久中文久久字幕| 午夜av一区二区三区| 99香蕉国产精品偷在线观看 | 久久黄色影视| 亚洲高清福利| 日韩久久不卡| 久久韩剧网电视剧| 亚洲国产一区视频| 七七婷婷婷婷精品国产| 日韩精品一区国产| 欧美捆绑视频| 在线观看欧美一区| 欧美激情在线视频二区| 日韩欧美在线免费| 国产一区在线不卡| 欧美13videosex性极品| 亚洲成人天堂网| 国产视色精品亚洲一区二区| 国产视频精品久久久| 18欧美乱大交hd1984| 久热精品在线| 加勒比视频一区| 九色视频网站在线观看| 亚洲国产激情一区二区三区| 久久久久久免费精品| 欧美日韩第一区日日骚| 97久久精品人人澡人人爽| 亚洲免费二区| 国产精品天堂蜜av在线播放| 最新在线地址| 亚洲中文字幕无码一区二区三区| 国产精品jvid在线观看蜜臀| 日韩国产精品一区| 岛国视频午夜一区免费在线观看| 国产精选一区二区三区| 亚洲精品一二三区区别| 日韩成人一区| 麻豆传媒在线完整视频|