面試記錄:事物和隔離級別

問題:數(shù)據(jù)庫的隔離級別
雖然知道,但是沒有刻意背過,面試一緊張直接忘了。
這個問題搞明白要從事物開始理解。
事物
所謂事物,就是將對數(shù)據(jù)庫的一系列操作(比如 sql)在邏輯上構成一個整體,一次事物要么全部執(zhí)行成功,要么全部執(zhí)行不成功。
事物存在的原因,主要是針對因某些原因?qū)е乱幌盗械臄?shù)據(jù)庫操作執(zhí)行不成功而造成的“跑了一半”的問題。
最經(jīng)典的轉(zhuǎn)賬例子:小明要向小紅轉(zhuǎn)賬1000塊,需要的操作是先從小明的賬戶減少1000塊錢,然后在小紅的賬號增加1000塊錢。如果這個過程在中間斷掉了,就有可能造成小明賬號少了錢,但是小紅賬號資金沒有增加。而如果這個操作使用了事物的話,小明的賬號會回滾到事物執(zhí)行前的狀態(tài),即他的賬號沒有減少資金的狀態(tài)。
提交事物就是用 sql 中的 Commit 操作。
事物有四大特性(ACID)
原子性(Atomicity):即前面提到的事物是邏輯上的一個整體,是程序最小的執(zhí)行單位,要么都跑完要么一點不跑。
一致性(Consistency):執(zhí)行事物前后的數(shù)據(jù)保持一致,譬如前面提到的轉(zhuǎn)賬場景,小明轉(zhuǎn)賬給小紅的1000塊錢是一致的,既沒有變多也沒有變少。
隔離性(Isolation):并發(fā)執(zhí)行下事物是“互不干涉”的,相互獨立。
持久性(Durabilily):事物所造成的影響是永久的。
其他經(jīng)驗:事物的原子、隔離、持久保證了數(shù)據(jù)的一致,即數(shù)據(jù)的一致性是目的,其他三項是手段。
并發(fā)事物下會造成問題
數(shù)據(jù)庫的操作事物一定是在并發(fā)狀態(tài)下執(zhí)行的,既然有并發(fā)和共享數(shù)據(jù),那就一定會有出現(xiàn)線程安全問題的風險
臟讀(Dirty read):一個事物1在執(zhí)行過程中修改了數(shù)據(jù),但是在這個事物1沒有提交時,有一個事物2來查詢了這條數(shù)據(jù),因為事物1修改的數(shù)據(jù)還未提交,所以事物2讀到的數(shù)據(jù)是“臟數(shù)據(jù)”,使用這種數(shù)據(jù)有可能會出錯,這種情況即為 臟讀。
丟失修改(Lost to modify):一個事物1在執(zhí)行過程中修改了數(shù)據(jù),在事物1還未提交時,事物2在執(zhí)行中也修改了這條數(shù)據(jù),這時由于事物1還沒有提交,事物2對數(shù)據(jù)造成的修改相當于將事物1的修改給“丟失”掉了,這種情況稱為丟失修改。
不可重復讀(Unrepeatable read):事物1在執(zhí)行中要讀取一條數(shù)據(jù)兩次及以上,但是在執(zhí)行過程中這條數(shù)據(jù)被另一條事物2給修改了,造成了事物1在執(zhí)行中多次操作同一數(shù)據(jù)情況不一致,這種情況稱為“不可重復讀”
幻讀(Phantom read):事物1在執(zhí)行中讀取了幾條數(shù)據(jù),此時有事物2進行了插入或刪除數(shù)據(jù)的操作,此時如若事物1再次用同樣的查詢條件讀取數(shù)據(jù),會發(fā)現(xiàn)兩次讀取的數(shù)據(jù)行數(shù)不一樣,這種情況稱之為幻讀。
注意事項:
臟讀和丟失修改的區(qū)別為,臟讀只是第二條事物讀到了事物1修改但是未提交的數(shù)據(jù),沒有對這個數(shù)據(jù)進行修改操作。而丟失修改時事物2修改了事物1修改但未提交的數(shù)據(jù)。所以二者區(qū)別為事物2有沒有對事物1未提交數(shù)據(jù)的進行修改。
不可重復度和幻讀類似,區(qū)別為不可重復讀是事物2修改了行本身的數(shù)據(jù),而幻讀是事物2插入了新的行或刪除了某些行而造成的事物1多次讀取數(shù)據(jù)的條數(shù)不一致。
解決并發(fā)事物問題,SQL 標準定義的事物隔離級別
事物的隔離級別就是為了解決前面提到的并發(fā)事物問題。
讀未提交(READ-UNCOMMITTED) : 最低隔離級別,字面意思允許讀取未提交的數(shù)據(jù)。上述所有并發(fā)問題均沒有預防效果。
讀已提交(READ-COMMITTED):允許讀取已經(jīng)提交的數(shù)據(jù),沒有提交的數(shù)據(jù)不能讀(如果讀的話會讀到之前提交的舊數(shù)據(jù)),所以不會有臟讀問題,但是幻讀和不可重復讀仍可能發(fā)生
可重復讀(REPEATABLE-READ):對同一字段的多次讀取結果一致。除非讀取字段的事物本身修改了數(shù)據(jù),這種隔離級別僅有幻讀風險
可串行化(SERIALIZABLE):最高隔離級別,所有事物同步執(zhí)行,完全服從ACID。不會有并發(fā)事物問題的風險。
補充:MySQL 的默認隔離級別是可重復讀。
MySQL 的隔離級別基于鎖和 MVCC 機制共同實現(xiàn)的。串行化使用的是鎖機制,其余的使用MVCC機制實現(xiàn)隔離級別。