平常我們做業(yè)務(wù)的時(shí)候會(huì)經(jīng)常用到事務(wù),但是很少去關(guān)心事務(wù)的級(jí)別,實(shí)際上事務(wù)的級(jí)別的不同,對(duì)業(yè)務(wù)會(huì)產(chǎn)生不小的影響,比如有的級(jí)別的事務(wù)可能會(huì)產(chǎn)生臟讀,而有的級(jí)別可能會(huì)產(chǎn)生幻讀.
READ UNCOMMITTED(未提交讀)
在未提交讀這個(gè)事務(wù)級(jí)別中,一個(gè)事務(wù)可以讀取到另外一個(gè)事務(wù)未提交的數(shù)據(jù).
例如 A 事務(wù)更新了一個(gè)字段,但是未提交在 B 事務(wù)中,讀取id為999的記錄的name字段的時(shí)候,name的值為'aaa',可是 A 事務(wù)并沒(méi)有commit,所以name = 'aaa'有可能是會(huì)被回滾的,那么,A 事務(wù)這個(gè)操作就相當(dāng)于讀取了一個(gè)錯(cuò)誤的值.
A 事務(wù)這次讀取被稱為臟讀(Dirty Read)
READ COMMITTED(提交讀)
提交讀這個(gè)事務(wù)級(jí)別中,一個(gè)事務(wù)可以讀取到另外一個(gè)事務(wù)提交之后的數(shù)據(jù).
例如 A 事務(wù)讀取到了id為999的記錄的name字段為aaa ,然后 B 事務(wù)這個(gè)時(shí)候更新了這條記錄的name值,并且提交了,這個(gè)時(shí)候 A 事務(wù)再次讀取name的話,name的值就是bbb了,所以在一個(gè)事務(wù)中,對(duì)一個(gè)字段進(jìn)行多次讀取,可能得到的值不同.
REPEATABLE READ(可重復(fù)度)
可重復(fù)讀這個(gè)事務(wù)級(jí)別中,一個(gè)事務(wù)重復(fù)去讀的字段不會(huì)改變.
例如 A 事務(wù)讀取到了id為999的記錄的name值為aaa,然后 B 事務(wù)中把name改成了bbb,并且 B 事務(wù)提交了,A 事務(wù)再次去讀name的時(shí)候并不會(huì)讀取到bbb,所以 A 事務(wù)相當(dāng)于在一個(gè)獨(dú)立的世界,外界的任何改動(dòng)不會(huì)影響 A 事務(wù).
但是,可重復(fù)讀會(huì)導(dǎo)致幻讀出現(xiàn),什么是幻讀呢,舉個(gè)例子:
A 事務(wù)查詢一個(gè)表,表里只有一條記錄,id為1,但是這個(gè)時(shí)候 B 事務(wù)插入了一條數(shù)據(jù),id為2,A 事務(wù)因?yàn)椴恢烙衖d為2的數(shù)據(jù),所以這個(gè)時(shí)候A也插入了一條id為2的數(shù)據(jù),這個(gè)時(shí)候肯定會(huì)插入失敗.這種情況就是幻讀
MYSQL中的innoDB通過(guò)MVCC(多版本并發(fā)控制)解決了幻讀,另外MYSQL的默認(rèn)事務(wù)級(jí)別就是可重復(fù)讀
SERIALIZABLE(可串行化)
可串行化事務(wù)級(jí)別,把讀取的每一行數(shù)據(jù)都加了鎖
加鎖了的有點(diǎn)就是,避免了臟讀和幻讀,另外還避免了不可重復(fù)讀的可能性,但是因?yàn)榧渔i了,減少了很大的并發(fā)性,因?yàn)橥粫r(shí)刻,只有一個(gè)線程能夠獲取到鎖.還可能導(dǎo)致大量超時(shí)問(wèn)題.