1. 髒讀session
所謂的髒讀就是指一個事務讀取了另外一個事務未提取的數據。spa
試想一下:a帳戶要給b帳戶100元購買商品,若是a帳戶開啓一個事務,執行下面的update語句作了以下轉帳的工做:命令行
update account set money=money-100 where name='a'; update account set money=money+100 where name='b';
若是a帳戶先不提交事務,通知b帳戶來查詢,因爲b的隔離級別比較低,此時就會讀取a事務中未提交的數據,發現a確實給本身轉了100元,而後給a發貨,等b發貨成功以後,a再將事務回滾,此時b就會受到損傷,這就是髒讀形成的。線程
爲了演示上面的狀況,這裏咱們開啓了兩個命令行窗口(至關於開啓兩個線程),分別模擬a帳戶和b帳戶,以下:3d
(1)設置b帳戶中事務的隔離級別code
你們都知道MySQL的默認隔離級別是Repeatable Read(可重複讀),該級別是能夠避免髒讀的,所以須要將b帳戶中事務的隔離級別設置爲Read Uncommitted(讀未提交),具體語句以下:blog
set session transaction isolation level read uncommitted;
以下:事務
上述語句之中,session表示當前會話,transaction就表示事務,isolation表示隔離,level表示級別,read uncommitted表示當前的隔離級別,該語句執行成功以後,使用select語句查詢事務的隔離級別,結果以下:it
select @@tx_isolation;
以下:io
從上述結果能夠看出,b帳戶的事務隔離級別以及修改成Read Uncommitted,接下來就是演示髒讀的狀況
(2)演示髒讀
b帳戶:爲了證實出現了髒讀的狀況,首先在b帳戶中開戶一個事務,並在該事務中查詢當前帳戶的餘額信息,查詢結果以下:
start transaction; select * from account;
以下:
a帳戶:在a帳戶中開啓一個事務,並在當前窗口中執行轉帳功能,具體語句以下:
start transaction; update account set money=money-100 where name='a'; update account set money=money+100 where name='b';
以下:
須要注意的是:此時不要提交事務,若是提交事務就沒法演示出現髒讀的狀況。
b帳戶:a帳戶執行完轉帳語句後,b帳戶查詢當前帳戶,以下:
從上面的查詢結果來看,a帳戶已經成功給b帳戶轉帳了100元,這是因爲b帳戶的事務隔離級別比較低,所以纔讀取了a帳戶尚未提交的數據內容,出現了髒讀的狀況,這時候,b誤覺得a帳戶以及轉帳成功,便會給a發貨,當b發貨以後a若是不提交事務將事務回滾,b就會受到損失。
上面演示完畢了,須要將a帳戶中的事務回滾,b帳戶中的事務提交。
(3)設置b帳戶的事務隔離級別
爲了防止髒讀發生,能夠將b帳戶中的事務隔離級別設置爲Read Committed(讀提交),該級別會避免髒讀,具體語句以下:
set session transaction isolation level read committed;
上述的語句執行成功以後,b帳戶的隔離級別已經設置成Read Committed
(4)驗證是否出現髒讀
b帳戶:爲了說明沒有出現髒讀的狀況,首先要在b帳戶中開啓一個事務,並在該事務中查詢各帳戶的餘額狀況,查詢結果以下:
a帳戶:在a帳戶中從新開啓一個事務,實現了轉帳功能,以下:
start transaction; update account set money=money-100 where name='a'; update account set money=money+100 where name='b';
b帳戶:當a 帳戶轉帳成功以後,能夠在b帳戶中再次查詢各帳戶的餘額信息,查詢結果以下:
經過上面的對比兩次查詢結果能夠發現,b帳戶在同一個事務中的查詢結果是一致的,並無查詢到a帳戶中未提交的內容,所以能夠說明Read Committed 隔離級別能夠避免髒讀,最後分別將a帳戶和b帳戶中的事務回滾(方便之後演示)。