新聞中心
在現(xiàn)代化的大數(shù)據(jù)時(shí)代,數(shù)據(jù)庫已經(jīng)成為各大企業(yè)或者公司必不可少的一部分。然而,隨著數(shù)據(jù)庫使用量的增長,各種各樣的問題也開始顯露出來。其中一個(gè)比較常見的問題便是臟讀,臟讀指的是當(dāng)一個(gè)事務(wù)開始讀取一個(gè)數(shù)據(jù)并且還沒有提交時(shí),另一個(gè)事務(wù)對該數(shù)據(jù)進(jìn)行了修改并且提交后,之一個(gè)事務(wù)再次讀到該數(shù)據(jù)時(shí),讀到的是已經(jīng)被更改過的數(shù)據(jù),導(dǎo)致數(shù)據(jù)一致性問題。毫無疑問,解決數(shù)據(jù)庫臟讀問題已成為每個(gè)數(shù)據(jù)庫管理員的頭等大事。

郴州網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),郴州網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為郴州上千多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個(gè)售后服務(wù)好的郴州做網(wǎng)站的公司定做!
那么,有哪些呢?
1. 設(shè)置合適的隔離級別
數(shù)據(jù)庫是一個(gè)多用戶系統(tǒng),不同的用戶并發(fā)訪問同一數(shù)據(jù)是很常見的情況,而事務(wù)隔離級別就是用來控制并發(fā)事務(wù)之間相互干擾的。通常情況下,我們可以在事務(wù)開始之前通過設(shè)置事務(wù)隔離級別來保證數(shù)據(jù)不會出現(xiàn)臟讀問題。在MySQL中,我們設(shè)置的隔離級別越高,越能讓我們避免臟讀的問題。在InnoDB引擎下,我們可以設(shè)置如下幾種隔離級別:
讀未提交(Read uncommitted):臟讀,一般情況下不應(yīng)該使用。
讀已提交(Read committed):解決臟讀問題,但是無法解決幻讀問題。
可重復(fù)讀(Repeatable read):將解決臟讀和幻讀問題,在并發(fā)環(huán)境中比較常用。
序列化(Serializable):更高的隔離級別,在所有場景下都能夠保證數(shù)據(jù)的一致性,缺點(diǎn)是并發(fā)性能較差。
2. 使用鎖機(jī)制
鎖機(jī)制是一種比較常見的解決并發(fā)問題的方法,通過在讀取和修改的數(shù)據(jù)上加鎖來協(xié)調(diào)事務(wù)的并發(fā)執(zhí)行。在MySQL中,我們可以使用共享鎖和排它鎖進(jìn)行并發(fā)控制。例如,當(dāng)兩個(gè)事務(wù)同時(shí)更新同一行數(shù)據(jù)時(shí),只有一個(gè)事務(wù)能夠成功地對該行數(shù)據(jù)加上排它鎖,另一個(gè)事務(wù)需要等待之一個(gè)事務(wù)提交之后才能對該行數(shù)據(jù)進(jìn)行修改。這種方式雖然能夠有效避免臟讀的問題,但是也會造成一定的性能損失。
3. 使用MVCC(多版本并發(fā)控制)
MVCC是MySQL中常用的一種解決并發(fā)問題的方式,它的核心思想是為每個(gè)事務(wù)創(chuàng)建一個(gè)視圖,該視圖看到的數(shù)據(jù)與當(dāng)前數(shù)據(jù)庫中的數(shù)據(jù)相同,但是在該事務(wù)提交之前不會被其他事務(wù)修改。因此,即使其他事務(wù)修改了同一行數(shù)據(jù),這個(gè)事務(wù)所看到的也是原始數(shù)據(jù),從而避免了臟讀的發(fā)生。
4. 應(yīng)用程序?qū)哟紊系奶幚?/p>
除了數(shù)據(jù)庫本身的優(yōu)化,我們還可以通過應(yīng)用程序?qū)哟紊系奶幚韥肀M可能地避免或減少臟讀問題。例如,我們可以通過鎖機(jī)制來保證只有一個(gè)會話可以修改一個(gè)特定的數(shù)據(jù),從而避免其他會話從該數(shù)據(jù)中讀取到臟數(shù)據(jù)。
盡管臟讀問題非常普遍,但是它并不是無解的問題。通過選擇合適的隔離級別、使用鎖機(jī)制、使用MVCC等數(shù)據(jù)庫優(yōu)化技術(shù),以及在應(yīng)用程序?qū)哟紊系奶幚?,我們都能夠有效地解決臟讀的問題,從而保證數(shù)據(jù)的一致性。在工作中,我們應(yīng)該根據(jù)具體使用場景和業(yè)務(wù)需求,選擇最適合的方案。
相關(guān)問題拓展閱讀:
- SQL數(shù)據(jù)庫多用戶操作同一條數(shù)據(jù)(多個(gè)用戶同時(shí)對同一數(shù)據(jù)進(jìn)行操作)
- 如何處理數(shù)據(jù)庫并發(fā)問題
SQL數(shù)據(jù)庫多用戶操作同一條數(shù)據(jù)(多個(gè)用戶同時(shí)對同一數(shù)據(jù)進(jìn)行操作)
sql多用戶訪問數(shù)據(jù)庫其實(shí)就是事務(wù)并發(fā),會引起如下問題:
1、臟讀:一個(gè)事務(wù)讀取到了另外一個(gè)事務(wù)沒有提交的數(shù)據(jù)
事務(wù)1:更新一條數(shù)據(jù)
事務(wù)2:讀取事務(wù)1更新的記錄
事務(wù)1:調(diào)用commit進(jìn)行提交
此時(shí)事務(wù)2讀取到的數(shù)據(jù)是保存在數(shù)據(jù)庫內(nèi)存中的數(shù)據(jù),稱為臟讀。
讀到的數(shù)據(jù)為臟數(shù)據(jù)
詳細(xì)解釋:
臟讀就是指:當(dāng)一個(gè)事務(wù)正在訪問數(shù)據(jù),并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時(shí),另外一個(gè)事務(wù)也訪問這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。因?yàn)檫@個(gè)數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個(gè)
事務(wù)讀到的這個(gè)數(shù)據(jù)是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作可能是不正確的。
2、不可重復(fù)讀:在同一事務(wù)中,兩次讀取同一數(shù)據(jù),得到內(nèi)容不同
事務(wù)1:查詢一條記錄
事務(wù)2:更新事務(wù)1查詢的記錄
事務(wù)2:調(diào)用commit進(jìn)行提交
事務(wù)1:再次查詢上次的記錄
此時(shí)事務(wù)1對同一數(shù)據(jù)查詢了兩次,可得到的內(nèi)容不同,稱為不可重復(fù)讀。
3、幻讀:同一事務(wù)中,用同樣的操作讀取兩次,得到的記錄數(shù)不相同
事務(wù)1:查詢表中所有記錄
事務(wù)2:插入一條記錄
事務(wù)2:調(diào)用commit進(jìn)行提交
事務(wù)1:再次查詢表中所有記錄
此時(shí)事務(wù)1兩次查詢到的記錄是不一樣的,稱為幻讀
詳細(xì)解釋:
幻讀是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象,例如之一個(gè)事務(wù)對一個(gè)表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時(shí),第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù),這種修改是向表
中插入一行新數(shù)據(jù)。那么,以后就會發(fā)生操作之一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。
處理以上隔離級別的問題,采用如下方是:
事務(wù)隔離五種級別:
TRANSACTION_NONE不使用事務(wù)。
TRANSACTION_READ_UNCOMMITTED允許臟讀。
TRANSACTION_READ_COMMITTED防止臟讀,最常用的隔離級別,并且是大多數(shù)數(shù)據(jù)庫的默認(rèn)隔離級別
TRANSACTION_REPEATABLE_READ可以防止臟讀和不可重復(fù)讀,TRANSACTION_可以防止臟讀,不可重復(fù)讀取和幻讀,(事務(wù)串行化)會降低數(shù)據(jù)庫的效率
以上的五個(gè)事務(wù)隔離級別都是在Connection接口中定義的靜態(tài)常量,使用(intlevel)方法可以設(shè)置事務(wù)隔離級別。
如:con.(Connection.REPEATABLE_READ);
注意:事務(wù)的隔離級別受到數(shù)據(jù)庫的限制,不同的數(shù)據(jù)庫支持的的隔離級別不一定相同
1臟讀:修改時(shí)加排他鎖,直到事務(wù)提交后才釋放,讀取時(shí)加共享鎖,讀取完釋放事務(wù)1讀取數(shù)據(jù)時(shí)加上共享鎖后(這樣在事務(wù)1讀取數(shù)據(jù)的過程中,其他事務(wù)就不會修改該數(shù)據(jù)),不允許任何事物操作該數(shù)據(jù),只能讀取,之后1如果有更新操作,那么會轉(zhuǎn)換為排他鎖,其他事務(wù)更無權(quán)參與進(jìn)來讀寫,這樣就防止了臟讀問題。
但是當(dāng)事務(wù)1讀取數(shù)據(jù)過程中,有可能其他事務(wù)也讀取了該數(shù)據(jù),讀取完畢后共享鎖釋放,此時(shí)事務(wù)1修改數(shù)據(jù),修改完畢提交事務(wù),其他事務(wù)再次讀取數(shù)據(jù)時(shí)候發(fā)現(xiàn)數(shù)據(jù)不一致,就會出現(xiàn)不可重復(fù)讀問題,所以這樣不能夠避免不可重復(fù)讀問題。
2不可重復(fù)讀:讀取數(shù)據(jù)時(shí)加共享鎖,寫數(shù)據(jù)時(shí)加排他鎖,都是事務(wù)提交才釋放鎖。讀取時(shí)候不允許其他事物修改該數(shù)據(jù),不管數(shù)據(jù)在事務(wù)過程中讀取多少次,數(shù)據(jù)都是一致的,避免了不可重復(fù)讀問題
3幻讀問題:采用的是范圍鎖RangeSRangeS_S模式,鎖定檢索范圍為只讀,這樣就避免了幻影讀問題。
如何處理數(shù)據(jù)庫并發(fā)問題
想要知道如何處理數(shù)據(jù)并發(fā),自然需要先了解數(shù)據(jù)并發(fā)。
什么是數(shù)據(jù)并發(fā)操作呢?
就是同一時(shí)間內(nèi),不同的線程同時(shí)對一條數(shù)據(jù)進(jìn)行讀寫操作。
在互聯(lián)網(wǎng)時(shí)代,一個(gè)系統(tǒng)常常有很多人在使用,因此就可能出現(xiàn)高并發(fā)的現(xiàn)象,也就是不同的用戶同時(shí)對一條數(shù)老梁廳據(jù)進(jìn)行操作,如果沒有有效的處理,自然就會出現(xiàn)數(shù)據(jù)的異常。而最常見的一種數(shù)據(jù)并發(fā)的場景就是電商中的秒殺,成千上萬個(gè)用戶對在極端的時(shí)間內(nèi),搶購一個(gè)商品。針對這種場景,商品的庫存就是一個(gè)需要控制的數(shù)據(jù),而多個(gè)用戶對在同一時(shí)間對庫存進(jìn)行重寫,一個(gè)不小心就可能出現(xiàn)超賣的情況。
針對這種情況,我們?nèi)绾斡行У奶幚頂?shù)據(jù)并發(fā)呢?
之一種方案、數(shù)據(jù)庫鎖
從鎖的基本屬性來說,可以分為兩侍隱種:一種是共享鎖(S),一種是排它鎖(X)。在MySQL的數(shù)據(jù)庫中,是有四種隔離級別的,會在讀寫的時(shí)候,自動的使用這兩種鎖,防止數(shù)據(jù)出現(xiàn)混亂。
這四種隔離級別分別是:
讀未提交(Read Uncommitted)
讀提交(Read Committed)
可重復(fù)讀(Repeated Read)
串行化(Serializable)
當(dāng)然,不同的隔離級別,效率也是不同的,對于數(shù)據(jù)的一致性保證也就有不同的結(jié)果。而這些可能出現(xiàn)的又有哪些呢?
臟讀(dirty read)
當(dāng)事務(wù)與事務(wù)之間沒有任何隔離的時(shí)候,就可能會出現(xiàn)臟讀。例如:商家想看看所有的訂單有哪些,這時(shí),用戶A提交了一個(gè)訂單,但事務(wù)還沒提交,商家卻看到了這個(gè)訂單。而這時(shí)就會出現(xiàn)一種問題,當(dāng)商家去操作這個(gè)訂單時(shí),可能用戶A的訂單由于部分問題,導(dǎo)致數(shù)據(jù)回滾,事務(wù)沒有提交,這時(shí)商家的操作就會失去目標(biāo)。
不可重復(fù)讀(unrepeatable read)
一個(gè)事務(wù)中,兩次讀操作出來的同一條數(shù)據(jù)值不同,就是不可重復(fù)讀。
例如:我們有一個(gè)事務(wù)A,需要去查詢一下商品庫存,然后做扣減,這時(shí),事務(wù)B操作了這個(gè)商品,扣減了一部分庫存,當(dāng)事務(wù)A再次去查詢商品庫存的時(shí)候,發(fā)現(xiàn)這一次的結(jié)果和上次不同了,這就是不可重復(fù)讀。
幻讀(phantom problem)
一個(gè)事務(wù)中,兩次讀操作出來的結(jié)果集不同,就是幻讀。
例如:一個(gè)事務(wù)A,去查詢現(xiàn)在已經(jīng)支付的訂單有哪些,得到了一個(gè)結(jié)果集。這時(shí),事務(wù)B新提交了一個(gè)訂單,當(dāng)事務(wù)A再次去查詢時(shí),就會出現(xiàn),兩次得到的結(jié)果集不同的情況,也就是幻讀了。
那針對這些結(jié)果,不同的隔離級別可以干什么呢?
“讀未提(Read Uncommitted)”能預(yù)防啥?啥都預(yù)防不了。
“讀提交(Read Committed)”能預(yù)防啥?使用“
快照
讀(Snapshot Read)”方式,避免“臟讀”,但是可能出現(xiàn)“不可重復(fù)讀”和“幻讀”。
“可重復(fù)讀(Repeated Red)”能預(yù)防啥?使用“快照讀(Snapshot Read)”方式,鎖住被讀取記錄,避免出現(xiàn)“臟讀”、“不可重復(fù)讀”,但是可能出現(xiàn)“幻讀”。
“串行化(Serializable)”能預(yù)防啥?有效避免“臟讀”、“不可重復(fù)讀”、“幻讀”,不過運(yùn)行效率奇差。
好了,鎖說完了,但是,我們的數(shù)據(jù)庫鎖,并不能有效的解決并發(fā)的問題,只是盡可能保證數(shù)據(jù)的一致性,當(dāng)并發(fā)量特別大時(shí),數(shù)據(jù)庫還是容易扛不住。那解決數(shù)據(jù)并發(fā)的另一個(gè)手段就是,盡可能的提高處理的速度。
因?yàn)閿?shù)據(jù)的IO要提升難度比較大,那么通過其他的方式,對數(shù)據(jù)進(jìn)行處理,減少數(shù)據(jù)庫的IO,就渣帶是提高并發(fā)能力的有效手段了。
最有效的一種方式就是:緩存
想要減少并發(fā)出現(xiàn)的概率,那么讀寫的效率越高,讀寫的執(zhí)行時(shí)間越短,自然數(shù)據(jù)并發(fā)的可能性就變小了,并發(fā)性能也有提高了。
還是用剛才的秒殺舉例,我們?yōu)榈木褪潜WC庫存的數(shù)據(jù)不出錯(cuò),賣出一個(gè)商品,減一個(gè)庫存,那么,我們就可以將庫存放在內(nèi)存中進(jìn)行處理。這樣,就能夠保證庫存有序的及時(shí)扣減,并且不出現(xiàn)問題。這樣,我們的數(shù)據(jù)庫的寫操作也變少了,執(zhí)行效率也就大大提高了。
當(dāng)然,常用的分布式緩存方式有:Redis和Memcache,Redis可以持久化到硬盤,而Memcache不行,應(yīng)該怎么選擇,就看具體的使用場景了。
當(dāng)然,緩存畢竟使用的范圍有限,很多的數(shù)據(jù)我們還是必須持久化到硬盤中,那我們就需要提高數(shù)據(jù)庫的IO能力,這樣避免一個(gè)線程執(zhí)行時(shí)間太長,造成線程的阻塞。
那么,讀寫分離就是另一種有效的方式了
當(dāng)我們的寫成為了瓶頸的時(shí)候,讀寫分離就是一種可以選擇的方式了。
我們的
讀庫
就只需要執(zhí)行讀,寫庫就只需要執(zhí)行寫,把讀的壓力從主庫中分離出去,讓主庫的資源只是用來保證寫的效率,從而提高寫操作的性能。
關(guān)于數(shù)據(jù)庫處理臟讀的方法的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都服務(wù)器托管選創(chuàng)新互聯(lián),先上架開通再付費(fèi)。
創(chuàng)新互聯(lián)(www.cdcxhl.com)專業(yè)-網(wǎng)站建設(shè),軟件開發(fā)老牌服務(wù)商!微信小程序開發(fā),APP開發(fā),網(wǎng)站制作,網(wǎng)站營銷推廣服務(wù)眾多企業(yè)。電話:028-86922220
文章題目:解決數(shù)據(jù)庫臟讀的有效方法 (數(shù)據(jù)庫處理臟讀的方法)
網(wǎng)頁鏈接:http://m.fisionsoft.com.cn/article/dpdpscc.html


咨詢
建站咨詢
