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ù) 并進(jìn)行查詢

5.此時TA進(jìn)行數(shù)據(jù)修改,并提交

6.B再次查詢可以看到A事務(wù)已經(jīng)提交的結(jié)果

根據(jù)測試可以發(fā)現(xiàn),先開啟的事務(wù)TA在事務(wù)TB提交之前進(jìn)行的查詢和TB提交之后進(jìn)行的第二次查詢,兩次查詢結(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的實(shí)現(xiàn)有一些差別:
事務(wù)以排他鎖的形式修改原始數(shù)據(jù)
把修改前的數(shù)據(jù)存放于Undo log,通過回滾指針與主數(shù)據(jù)關(guān)聯(lián)
修改成功(commit)啥都不做,失敗則恢復(fù)Undo log中的數(shù)據(jù)(rollback)