1.設(shè)置為讀已提交
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
2.此時TA執(zhí)行插入难菌,并查詢想罕,可以查詢到結(jié)果
3.TB不能查到結(jié)果
證明已經(jīng)不能讀到未提交的數(shù)據(jù)
但是仍然存在不可重復(fù)讀問題 (同一事務(wù)內(nèi)兩次讀的數(shù)據(jù)不一致)
4.為了演示效果秘蛇,把用戶數(shù)據(jù)插入數(shù)據(jù)庫并提交,此時表中有一條id為1的 name為aaa的記錄
TB開啟一個事務(wù) 并進行查詢
5.此時TA進行數(shù)據(jù)修改,并提交
6.B再次查詢可以看到A事務(wù)已經(jīng)提交的結(jié)果
根據(jù)測試可以發(fā)現(xiàn)治筒,先開啟的事務(wù)TA在事務(wù)TB提交之前進行的查詢和TB提交之后進行的第二次查詢,兩次查詢結(jié)果不一致舷蒲,出現(xiàn)不可重復(fù)讀情況耸袜。
如果要避免不可重復(fù)讀,至少要把事務(wù)隔離級別設(shè)為:1.3 REPEATABLE READ(可重復(fù)讀)
InnoDB采用了MVCC(Multiversion Concurrency Control)多版本并發(fā)控制牲平,避免不可重復(fù)讀堤框。MVCC只在 READ COMMITTED? 和 REPEATABLE READ? 2個隔離級別下工作。MVCC會建立多個ReadView纵柿,RC是語句級多版本(事務(wù)的多條只讀語句蜈抓,創(chuàng)建不同的ReadView,代價更高)昂儒,RR是事務(wù)級多版本(一個事務(wù)有一個ReadView)资昧。由于RC中未提交的事務(wù),不允許其他事務(wù)看到荆忍,但是本身事務(wù)需要看到格带,所以執(zhí)行多條語句時撤缴,都需要建立新的ReadView,以支持本事務(wù)后面的查詢叽唱。
注:
MVCC本意應(yīng)該是下面的樣子:
每行數(shù)據(jù)都存在一個版本屈呕,每次數(shù)據(jù)更新時都更新該版本
修改時Copy出當(dāng)前版本隨意修改(類似于Java并發(fā)包中的CopyOnWrie操作),各個事務(wù)之間無干擾
保存時比較版本號棺亭,如果成功(commit)虎眨,則覆蓋原記錄;失敗則放棄copy(rollback)
但是InnoDB的實現(xiàn)有一些差別:
事務(wù)以排他鎖的形式修改原始數(shù)據(jù)
把修改前的數(shù)據(jù)存放于Undo log镶摘,通過回滾指針與主數(shù)據(jù)關(guān)聯(lián)
修改成功(commit)啥都不做嗽桩,失敗則恢復(fù)Undo log中的數(shù)據(jù)(rollback)