五分钟了解数据库事务隔离
前言
什么是事務隔離呢?們知道,關系型數(shù)據(jù)基本都支持事務,事務具備四個特性,分別是:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability),也就是傳說中的ACID,有了這四個特性,才能保證事務中所有數(shù)據(jù)的正確性。
其中事務的隔離性就是指多個并發(fā)的線程同時操作同一條記錄時,每個事務中的操作或數(shù)據(jù)不能被其他事務干擾。如果沒有隔離會怎么樣?會產(chǎn)生各種各樣的問題,比如修改丟失、臟讀、幻讀等。
下面我們一起看下事務隔離的演變,假設有兩個事務線程同時要操作A記錄。
1、修改丟失
事務1讀取A=100,加上20后等于120寫回數(shù)據(jù)庫,同時事務2讀取A=100,減去50后等于70寫回數(shù)據(jù)庫。這時事務1的操作就會被事務2覆蓋,如下圖:
為了解決修改被覆蓋的問題,數(shù)據(jù)庫給A加了寫鎖(排他鎖),這樣事務1在修改前先獲取A的排他鎖,等事務提交后再釋放鎖,如下圖:
2、臟讀
加了排他鎖后,修改丟失的問題得到了解決,雖然寫數(shù)據(jù)的問題通過鎖解決了,但讀卻沒有解決。比如在事務1在操作A的過程中,事務2讀取A,這時就會發(fā)生臟讀,如下圖:
為了解決臟讀的問題,得把讀數(shù)據(jù)也要加個讀鎖(共享鎖),并定了規(guī)則:如果加了排他鎖,就無法獲取共享鎖,反之,如果加了共享鎖,則無法獲取排他鎖,且共享鎖在讀取完就要釋放,如下圖:
3、不可重復讀
臟讀的問題通過共享鎖解決了,但共享鎖的規(guī)則是讀取完數(shù)據(jù)后立馬釋放共享鎖,這樣效率很高,但會引起一個問題,即在事務1中讀取A的值后必須立刻釋放鎖,正巧事務2這時修改了A的值,然后事務1再讀取A的值時發(fā)現(xiàn)和剛才讀的怎么不一樣了?如下圖:
為了保證同一個記錄在當前事務中的值保持一致(即可重復讀),則共享鎖也必須在事務結束后才能釋放,如下圖:
4、幻讀
可重復讀的問題解決了,現(xiàn)在遇到了一個更詭異的問題:事務1選擇賬號表中所有性別為女的行,并做了修改,修改完成后再查詢下記錄發(fā)現(xiàn)多了一條,原來是事務2在事務1修改的過程中又添加了一條性別為女的行,為了解決這樣問題(幻讀),只能將隔離級別再調(diào)高,每個事務按順序執(zhí)行,即串行化。
5、小結
通過以上整合的演化,我們發(fā)現(xiàn)隔離級別越來越強,但并發(fā)效率卻越來越低,每一種隔離級別其實都是為解決特定的問題,做個小結如下:
讀未提交(Read Uncommitted):寫數(shù)據(jù)時加了排他鎖,直到事務結束,讀數(shù)據(jù)時不加鎖,能避免修改丟失,但會讀到?jīng)]有提交或回滾的數(shù)據(jù)。
讀提交(Read Committed):寫數(shù)據(jù)時加了排他鎖,直到事務結束,讀數(shù)據(jù)加上共享鎖,讀完立即釋放,能避免修改丟失、臟讀,但會出現(xiàn)不可重復讀的問題。
可重復讀(Repeatable read):寫數(shù)據(jù)時加了排他鎖,直到事務結束,讀數(shù)據(jù)加上共享鎖,直到事務結束,能避免修改丟失、臟讀、不可重復讀,但會出現(xiàn)幻讀等問題。
串行化(Serializable):事務排隊執(zhí)行,雖然能解決以上所有問題,但效率太低了。
PS:一般沒有數(shù)據(jù)庫用串行化,性能比較低,常用的是已提交讀和可重復讀。而已提交讀和可重復讀的實現(xiàn)主要是ReadView,即MVCC(多版本控制),此內(nèi)容單獨一篇文章講解,敬請關注。
總結
以上是生活随笔為你收集整理的五分钟了解数据库事务隔离的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开源网站云查杀方案,搭建自己的云杀毒。
- 下一篇: 基于 Redis 实现 CAS 操作