針對MySQL并發事務這一塊,之前看了網上很多部落格和資料,講的都比較的模棱兩可,或者是隻有文字描述不夠形象易懂,最近有時間将我之前的學習筆記整理了一下來詳細講一講事務并發都會引起哪些問題?以及隔離級别是什麼?InnoDB引擎是如何通過隔離級别來解決并發事務所引起的問題?
何為讀已送出
(相當于目前讀,也就是這種隔離級别下隻要有其他事務對資料進行更改的操作且送出,那麼目前事務Select就會查詢到最新的資料)
從字面上我們就可以了解,即一個事務操作過程中可以讀取到其他事務已經送出的資料。
事務中的每次讀取操作,讀取到的都是資料庫中其他事務已送出的最新的資料(相當于目前讀),也就是不能讀取到其他事務還未送出的資料,是以在讀已送出這個隔離級别下就解決了髒讀的問題
何為可重複讀
(又稱快照讀,當事務A開啟時便對資料産生一個快照,與此同時無論其他事務對資料如何操作,在目前這個事務A裡查詢到的都是快照中的資料)(又稱快照讀,當事務A開啟時便對資料産生一個快照,與此同時無論其他事務對資料如何操作,在目前這個事務A裡查詢到的都是快照中的資料)
一個事務操作中對于一個讀取操作不管多少次,讀取到的結果都是一樣的。是以在可重複讀這個隔離級别下就解決了一個事務當中前後讀取到的結果不一緻的情況,進而解決了不可重複讀的問題
下面就通過實際操作來看看髒讀,不可重複讀,幻讀這三個現象是什麼樣的,以及在InnoDB各個隔離級别下是如何解決了這些并發事務問題的。
髒讀現象:
首先設定隔離級别為未送出讀
打開兩個視窗,同時執行事務A和B
此時事務B更新資料後并未送出,但可以看到事務A前後查詢到的資料不一樣,也就是讀取到了其他事務還未送出的資料,這也就是髒讀的現象
如何解決髒讀現象:
首先設定隔離級别為已送出讀:
打開兩個視窗,同時執行事務A和B:
上述流程可以看到當隔離級别為已送出讀時,已經解決了髒讀的情況,但是當事務B對資料進行更改且送出時,事務A卻出現了前後的查詢結果不一緻的情況,這種現象就叫做不可重複讀。
如何解決不可重複讀的現象:
首先設定隔離級别為可重複讀:
打開兩個視窗,同時執行事務A和B:
上述流程可以看到當隔離級别為可重複讀時,已經解決了不可重複讀的情況,當事務B對資料進行更改且送出時,事務A前後的查詢結果一緻,隻有當事務A送出後再開啟事務查詢時才會查到最新的資料。
幻讀現象:
首先設定隔離級别為可重複讀:
打開兩個視窗,同時執行事務A和B:
上述流程可以看到當隔離級别為可重複讀時,事務A,B同時執行,事務A先查詢到id=3是沒有資料的于是想要Insert,此時事務B也insert了id=3的資料但是事務A卻查詢不到,并且當事務A insert的時候卻提示了error,這種現象就稱為幻讀。
如何解決幻讀的現象:
首先設定隔離級别為串行化:
打開兩個視窗,同時執行事務A和B:
上述流程可以看到當隔離級别為序列化時,事務A,B同時執行,事務A先查詢到id=4是沒有資料,此時事務B想insert id=4的資料但是卻阻塞了,接下來事務A執行了insert id=4d的操作,并且隻要事務A不送出事務B都一直處于阻塞狀态中,當事務A送出後事務B才不再阻塞,但此時卻報錯提示id=4已存在,進而解決了幻讀的問題。
是以MySQL當中預設的隔離級别是可重複讀,一般也不會去手動更改。
綜上所述基本說清楚了在InnoDB引擎當中所産生的并發事務問題,是如何解決的,以及為什麼會有隔離級别這個概念,它們之間有什麼差別,作用又是什麼,希望本篇文章能夠幫助大家更有效地了解這一部分的知識。
原文連結:https://www.cnblogs.com/zhangpeiyao/p/16894442.html