每一個概念的產,都有個具體的場景,概念是對這個場景的描述。事務隔離級別這個概念也是,它就是 來描述這樣個問題:對於同 數據, 一個讀,另個寫,讀和寫究竟是誰等着誰,怎麼交互的。併發
爲麼不是兩個都讀,或者兩個都寫呢?兩個都讀,各讀各的,自己就存在問題嘛。兩個都寫,確定是先到者先寫,後到者等着先到者寫完纔開始寫,也沒啥衝突。衝突就發在個讀個寫上。性能
(爲描述,我們這定義A是讀的 ,B是寫的 。)學習
假如B先過來寫,A後過來讀,那就分爲以下兩種狀況:事務
狀況1、B先加把鎖,把要修改的數據鎖住,而後開始寫,A過來看着加鎖就等着,直到等着B寫完釋放鎖。這種狀況沒啥問題。這就是事務隔離級別中讀已提交描述的場景。A等B徹底寫 完才能讀。get
狀況2、B過來就開始寫,不加鎖,A而後就跟過來讀,B寫一點,A讀一點,B還沒寫完整就被A讀 ,這就是髒讀,由於B只是打打草稿,還沒最後提交定稿呢,隨時可能撤回重寫的。A讀的是B的草稿。這就是事務隔離級別中讀未提交描述的場景。互聯網
其實最複雜的狀況是A先過來讀,B後過來寫,而後A繼續讀。這 分爲四種狀況,分別對應四種事務隔離級別。技術
狀況1、A讀A的,B寫B的,這個跟上邊的狀況相似,A和B各幹各的,互不等待。qq
這樣就出現問題,A會讀到B尚未提交的數據,就是所謂的髒讀,也就是事務隔離級別中讀未提交的狀況。但這樣也有個優點,就是A和B同時進 ,併發程度最高,因此性能也會最好。 可是業務中不容許讀尚未寫完整的數據,怎麼辦呢,看下邊狀況 。經驗
狀況2、A讀A的,B寫的時候加鎖,A再讀的時候等待B寫完。總結
這種狀況就解決了讀未提交的問題。A若是發現B在寫,就等着B寫完再讀,這就保證A讀到的都是B寫完整的,這就是讀已提交。但這樣也會有個問題,A先讀這個數據,B後來過來加鎖修改這個數據,A再次讀取這個數據的時候發現和以前不同了,由於中途被B給修改了嘛,這就是不可重複讀。這裏能夠看到A須要等待下B,併發度明顯沒上邊的狀況好 ,因此性能也天然降低了點。但怎麼解決這個A連續讀兩次數據不一致的問題呢。看下邊狀況三。
狀況3、A讀的時候對要讀的數據加鎖,B要是修改A正在讀的數據,B就只能等着A先讀完,可是B能夠插入新的數據(這是考慮到儘量保證併發度)
這種狀況就解決了不可重複讀的問題,由於A讀的過程當中,B不能修改A讀的數據。這就是可重複讀。但問題是,A讀的時候只是要求B不能修改正在讀的數據,並無要求B不能插入新的 數據。若是B插入新的數據,那A的兩次讀取又不同 ,這是幻讀。(跟上邊狀況類似,這裏A第一次讀到的數據在第二次中並無被修改,只是第二次中數據變多 )。這裏也能夠看到,A在讀的過程當中,B只能老實的等着,除了插入新數據。併發度上要比上邊狀況更低 ,因此性能 進一步變差。那若是也不想出現幻讀怎麼辦呢?看下邊狀況四。
狀況4、A讀的時候,B 什麼也不能幹,只能等着,等A讀完 ,B纔開始寫。
這種狀況,上邊全部的問題都解決了,這就是串行化。由於讀和寫徹底串行。A在讀的過程當中,不再會被B打擾 。可是,問題就是性能嚴重降低,併發度成爲零。性能最差 。
到這裏應該把事務隔離級別說明白了,本質就是在性能和讀寫問題之間作權衡。要求讀寫上不能有任何問題,那就只好犧牲性能。
最後總結下:
讀未提交:A讀A的,B寫B的,互相讓。存在髒讀 。
讀已提交:A讀A的,B修改的時候須要加鎖,A再讀的時候須要等B寫完。存在不可重複度 。
可重複讀:A將正在讀的數據加鎖,B等待A讀完再寫。可是B能夠插入新的數據。存在幻讀。
串行化:A讀,B除了等着啥也不幹。性能最差。
---------------------------------分割線----------------------------
若是你是一個初學者,但願找個有經驗的過來讓幫助你,歡迎加入個人學習圈子:
我正在「JAVA互聯網技術」和朋友們討論有趣的話題,你一塊兒來吧?
https://t.xiaomiquan.com/aEQVNJe
也能夠加qq諮詢:936419373