MySQL InnooDB引擎之並發事務問題以及隔離級別的作用和區別

最近在複習MySQL事務,但網上很多部落格和資料可以說講的不是模稜兩可就是只有文字描述不夠形象易懂,下面通過我的學習來詳細講一講事務並發都會引起哪些問題?以及隔離級別是什麼?InnoDB引擎是如何通過隔離級別來解決並發事務所引起的問題?
image
image

何為讀已提交

(相當於當前讀,也就是這種隔離級別下只要有其他事務對數據進行更改的操作且提交,那麼當前事務Select就會查詢到最新的數據)

從字面上我們就可以理解,即一個事務操作過程中可以讀取到其他事務已經提交的數據。

事務中的每次讀取操作,讀取到的都是資料庫中其他事務已提交的最新的數據(相當於當前讀),也就是不能讀取到其他事務還未提交的數據,所以在讀已提交這個隔離級別下就解決了臟讀的問題

何為可重複讀

(又稱快照讀,當事務A開啟時便對數據產生一個快照,與此同時無論其他事務對數據如何操作,在當前這個事務A里查詢到的都是快照中的數據)(又稱快照讀,當事務A開啟時便對數據產生一個快照,與此同時無論其他事務對數據如何操作,在當前這個事務A里查詢到的都是快照中的數據)

一個事務操作中對於一個讀取操作不管多少次,讀取到的結果都是一樣的。所以在可重複讀這個隔離級別下就解決了一個事務當中前後讀取到的結果不一致的情況,從而解決了不可重複讀的問題

下面就通過實際操作來看看臟讀,不可重複讀,幻讀這三個現象是什麼樣的,以及在InnoDB各個隔離級別下是如何解決了這些並發事務問題的。

臟讀現象:

首先設置隔離級別為未提交讀
image

打開兩個窗口,同時執行事務A和B
image
此時事務B更新數據後並未提交,但可以看到事務A前後查詢到的數據不一樣,也就是讀取到了其他事務還未提交的數據,這也就是臟讀的現象

如何解決臟讀現象:

首先設置隔離級別為已提交讀:

image

打開兩個窗口,同時執行事務A和B:

image
image
上述流程可以看到當隔離級別為已提交讀時,已經解決了臟讀的情況,但是當事務B對數據進行更改且提交時,事務A卻出現了前後的查詢結果不一致的情況,這種現象就叫做不可重複讀。

如何解決不可重複讀的現象:

首先設置隔離級別為可重複讀:

image

打開兩個窗口,同時執行事務A和B:

image
image
上述流程可以看到當隔離級別為可重複讀時,已經解決了不可重複讀的情況,當事務B對數據進行更改且提交時,事務A前後的查詢結果一致,只有當事務A提交後再開啟事務查詢時才會查到最新的數據。

幻讀現象:

首先設置隔離級別為可重複讀:

image

打開兩個窗口,同時執行事務A和B:

image
上述流程可以看到當隔離級別為可重複讀時,事務A,B同時執行,事務A先查詢到id=3是沒有數據的於是想要Insert,此時事務B也insert了id=3的數據但是事務A卻查詢不到,並且當事務A insert的時候卻提示了error,這種現象就稱為幻讀。

如何解決幻讀的現象:

首先設置隔離級別為串列化:

image

打開兩個窗口,同時執行事務A和B:

image
image
image
上述流程可以看到當隔離級別為序列化時,事務A,B同時執行,事務A先查詢到id=4是沒有數據,此時事務B想insert id=4的數據但是卻阻塞了,接下來事務A執行了insert id=4d的操作,並且只要事務A不提交事務B都一直處於阻塞狀態中,當事務A提交後事務B才不再阻塞,但此時卻報錯提示id=4已存在,從而解決了幻讀的問題。
image

所以MySQL當中默認的隔離級別是不可重複讀,一般也不會去手動更改。

綜上所述基本說清楚了在InnoDB引擎當中所產生的並發事務問題,是如何解決的,以及為什麼會有隔離級別這個概念,它們之間有什麼區別,作用又是什麼,希望本篇文章能夠幫助大家更有效地理解這一部分的知識。

Tags: