隨筆 - 24  文章 - 0  trackbacks - 0
          <2010年12月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

           

          數(shù)據(jù)并發(fā)的問(wèn)題

           

          一個(gè)數(shù)據(jù)庫(kù)可能擁有多個(gè)訪問(wèn)客戶端,這些客戶端都可以并發(fā)方式訪問(wèn)數(shù)據(jù)庫(kù)。數(shù)據(jù)庫(kù)中的相同數(shù)據(jù)可能同時(shí)被多個(gè)事務(wù)訪問(wèn),如果沒(méi)有采取必要的隔離措施,就會(huì)導(dǎo)致各種并發(fā)問(wèn)題,破壞數(shù)據(jù)的完整性。這些問(wèn)題可以歸結(jié)為5類,包括3類數(shù)據(jù)讀問(wèn)題(臟讀、幻象讀和不可重復(fù)讀)以及2類數(shù)據(jù)更新問(wèn)題(第一類丟失更新和第二類丟失更新)。

          臟讀(dirty read

          事務(wù)讀取B事務(wù)尚未提交的更改數(shù)據(jù),并在這個(gè)數(shù)據(jù)的基礎(chǔ)上操作。如果恰巧B事務(wù)回滾,那么A事務(wù)讀到的數(shù)據(jù)根本是不被承認(rèn)的。來(lái)看取款事務(wù)和轉(zhuǎn)賬事務(wù)并發(fā)時(shí)引發(fā)的臟讀場(chǎng)景

          時(shí)間

          轉(zhuǎn)賬事務(wù)A

          取款事務(wù)B

          T1

          開(kāi)始事務(wù)

          T2

          開(kāi)始事務(wù)

          T3

               

          查詢賬戶余額為1000元    

          T4

                  

          取出500元把余額改為500元

          T5

          查詢賬戶余額為500元(臟讀)

          T6

          撤銷事務(wù)余額恢復(fù)為1000元

          T7

          匯入100元把余額改為600元

          T8

          提交事務(wù)

          B希望取款500元而后又撤銷了動(dòng)作,而A往相同的賬戶中轉(zhuǎn)賬100元,就因?yàn)?/span>A事務(wù)讀取了B事務(wù)尚未提交的數(shù)據(jù),因而造成賬戶白白丟失了500元。

          不可重復(fù)讀(unrepeatable read

           

          不可重復(fù)讀是指A事務(wù)讀取了B事務(wù)已經(jīng)提交的更改數(shù)據(jù)。假設(shè)A在取款事務(wù)的過(guò)程中,B往該賬戶轉(zhuǎn)賬100元,A兩次讀取賬戶的余額發(fā)生不一致:

          時(shí)間

          取款事務(wù)A

          轉(zhuǎn)賬事務(wù)B

          T1

          開(kāi)始事務(wù)

          T2

          開(kāi)始事務(wù)

                                    

          T3

                                        

          查詢賬戶余額為1000元     

          T4

          查詢賬戶余額為1000元

                                    

          T5

                            

          取出100元把余額改為900元

          T6

          提交事務(wù)                  

          T7

          查詢賬戶余額為900元(和T4讀取的不一致)

          在同一事務(wù)中,T4時(shí)間點(diǎn)和T7時(shí)間點(diǎn)讀取賬戶存款余額不一樣。

          幻象讀(phantom read)
              A事務(wù)讀取B事務(wù)提交的新增數(shù)據(jù),這時(shí)A事務(wù)將出現(xiàn)幻象讀的問(wèn)題。幻象讀一般發(fā)生在計(jì)算統(tǒng)計(jì)數(shù)據(jù)的事務(wù)中,舉一個(gè)例子,假設(shè)銀行系統(tǒng)在同一個(gè)事務(wù)中,兩次統(tǒng)計(jì)存款賬戶的總金額,在兩次統(tǒng)計(jì)過(guò)程中,剛好新增了一個(gè)存款賬戶,并存入100元,這時(shí),兩次統(tǒng)計(jì)的總金額將不一致:  

          時(shí)間

          統(tǒng)計(jì)金額事務(wù)A

          轉(zhuǎn)賬事務(wù)B

          T1

          開(kāi)始事務(wù)

          T2

          開(kāi)始事務(wù)

                       

          T3

          統(tǒng)計(jì)總存款數(shù)為10000元

                       

          T4

          新增一個(gè)存款賬戶,存款為100元

          T5

          提交事務(wù)     

          T6

          再次統(tǒng)計(jì)總存款數(shù)為10100元(幻象讀)


             
          如果新增數(shù)據(jù)剛好滿足事務(wù)的查詢條件,這個(gè)新數(shù)據(jù)就進(jìn)入了事務(wù)的視野,因而產(chǎn)生了兩個(gè)統(tǒng)計(jì)不一致的情況。
          幻象讀和不可重復(fù)讀是兩個(gè)容易混淆的概念,前者是指讀到了其它已經(jīng)提交事務(wù)的新增數(shù)據(jù),而后者是指讀到了已經(jīng)提交事務(wù)的更改數(shù)據(jù)(更改或刪除),為了避免這兩種情況,采取的對(duì)策是不同的,防止讀取到更改數(shù)據(jù),只需要對(duì)操作的數(shù)據(jù)添加行級(jí)鎖,阻止操作中的數(shù)據(jù)發(fā)生變化,而防止讀取到新增數(shù)據(jù),則往往需要添加表級(jí)鎖——將整個(gè)表鎖定,防止新增數(shù)據(jù)(Oracle使用多版本數(shù)據(jù)的方式實(shí)現(xiàn))。


          第一類丟失更新
              A
          事務(wù)撤銷時(shí),把已經(jīng)提交的B事務(wù)的更新數(shù)據(jù)覆蓋了。這種錯(cuò)誤可能造成很嚴(yán)重的問(wèn)題,通過(guò)下面的賬戶取款轉(zhuǎn)賬就可以看出來(lái): 
              

          時(shí)間

          取款事務(wù)A

          轉(zhuǎn)賬事務(wù)B

          T1

          開(kāi)始事務(wù)

           

          T2

          開(kāi)始事務(wù)

          T3

          查詢賬戶余額為1000元    

          T4

          查詢賬戶余額為1000元

          T5

          匯入100元把余額改為1100元

          T6

          提交事務(wù)

          T7

          取出100元把余額改為900元

          T8

          撤銷事務(wù)

          T9

          余額恢復(fù)為1000元(丟失更新)


          A
          事務(wù)在撤銷時(shí),“不小心”將B事務(wù)已經(jīng)轉(zhuǎn)入賬戶的金額給抹去了。
          第二類丟失更新
          A事務(wù)覆蓋B事務(wù)已經(jīng)提交的數(shù)據(jù),造成B事務(wù)所做操作丟失:  

          時(shí)間

          轉(zhuǎn)賬事務(wù)A

          取款事務(wù)B

          T1

           

          開(kāi)始事務(wù)

          T2

          開(kāi)始事務(wù)

                                   

          T3

                         

          查詢賬戶余額為1000元    

          T4

          查詢賬戶余額為1000元

                                   

          T5

          取出100元把余額改為900元

          T6

          提交事務(wù)           

          T7

          匯入100元

          T8

          提交事務(wù)

          T9

          把余額改為1100元(丟失更新)


             
          上面的例子里由于支票轉(zhuǎn)賬事務(wù)覆蓋了取款事務(wù)對(duì)存款余額所做的更新,導(dǎo)致銀行最后損失了100元,相反如果轉(zhuǎn)賬事務(wù)先提交,那么用戶賬戶將損失100元。

          數(shù)據(jù)庫(kù)鎖機(jī)制
             
          數(shù)據(jù)并發(fā)會(huì)引發(fā)很多問(wèn)題,在一些場(chǎng)合下有些問(wèn)題是允許的,但在另外一些場(chǎng)合下可能卻是致命的。數(shù)據(jù)庫(kù)通過(guò)鎖的機(jī)制解決并發(fā)訪問(wèn)的問(wèn)題,雖然不同的數(shù)據(jù)庫(kù)在實(shí)現(xiàn)細(xì)節(jié)上存在差別,但原理基本上是一樣的。
              按鎖定的對(duì)象的不同,一般可以分為表鎖定和行鎖定,前者對(duì)整個(gè)表進(jìn)行鎖定,而后者對(duì)表中特定行進(jìn)行鎖定。從并發(fā)事務(wù)鎖定的關(guān)系上看,可以分為共享鎖定和獨(dú)占鎖定。共享鎖定會(huì)防止獨(dú)占鎖定,但允許其它的共享鎖定。而獨(dú)占鎖定既防止其它的獨(dú)占鎖定,也防止其它的共享鎖定。為了更改數(shù)據(jù),數(shù)據(jù)庫(kù)必須在進(jìn)行更改的行上施加行獨(dú)占鎖定,INSERT、UPDATE、DELETE和SELECT FOR UPDATE語(yǔ)句都會(huì)隱式采用必要的行鎖定。下面我們介紹一下ORACLE數(shù)據(jù)庫(kù)常用的5種鎖定:
          ? 行共享鎖定:一般通過(guò)SELECT FOR UPDATE語(yǔ)句隱式獲得行共享鎖定,在Oracle中你也可以通過(guò)LOCK TABLE IN ROW SHARE MODE語(yǔ)句顯式獲得行共享鎖定。行共享鎖定并不防止對(duì)數(shù)據(jù)行進(jìn)行更改的操作,但是可以防止其它會(huì)話獲取獨(dú)占性數(shù)據(jù)表鎖定。允許進(jìn)行多個(gè)并發(fā)的行共享和行獨(dú)占性鎖定,還允許進(jìn)行數(shù)據(jù)表的共享或者采用共享行獨(dú)占鎖定;
          ? 行獨(dú)占鎖定:通過(guò)一條INSERT、UPDATE或DELETE語(yǔ)句隱式獲取,或者通過(guò)一條LOCK TABLE IN ROW EXCLUSIVE MODE語(yǔ)句顯式獲取。這個(gè)鎖定可以防止其它會(huì)話獲取一個(gè)共享鎖定、共享行獨(dú)占鎖定或獨(dú)占鎖定;
          ? 表共享鎖定:通過(guò)LOCK TABLE IN SHARE MODE語(yǔ)句顯式獲得。這種鎖定可以防止其它會(huì)話獲取行獨(dú)占鎖定(INSERT、UPDATE或DELETE),或者防止其它表共享行獨(dú)占鎖定或表獨(dú)占鎖定,它允許在表中擁有多個(gè)行共享和表共享鎖定。該鎖定可以讓會(huì)話具有對(duì)表事務(wù)級(jí)一致性訪問(wèn),因?yàn)槠渌鼤?huì)話在你提交或者回溯該事務(wù)并釋放對(duì)該表的鎖定之前不能更改這個(gè)被鎖定的表;
          ? 表共享行獨(dú)占:通過(guò)LOCK TABLE IN SHARE ROW EXCLUSIVE MODE語(yǔ)句顯式獲得。這種鎖定可以防止其它會(huì)話獲取一個(gè)表共享、行獨(dú)占或者表獨(dú)占鎖定,它允許其它行共享鎖定。這種鎖定類似于表共享鎖定,只是一次只能對(duì)一個(gè)表放置一個(gè)表共享行獨(dú)占鎖定。如果A會(huì)話擁有該鎖定,則B會(huì)話可以執(zhí)行SELECT FOR UPDATE操作,但如果B會(huì)話試圖更新選擇的行,則需要等待;
          ? 表獨(dú)占:通過(guò)LOCK TABLE IN EXCLUSIVE MODE顯式獲得。這個(gè)鎖定防止其它會(huì)話對(duì)該表的任何其它鎖定。

          事務(wù)隔離級(jí)別
              盡管數(shù)據(jù)庫(kù)為用戶提供了鎖的DML操作方式,但直接使用鎖管理是非常麻煩的,因此數(shù)據(jù)庫(kù)為用戶提供了自動(dòng)鎖機(jī)制。只要用戶指定會(huì)話的事務(wù)隔離級(jí)別,數(shù)據(jù)庫(kù)就會(huì)分析事務(wù)中的SQL語(yǔ)句,然后自動(dòng)為事務(wù)操作的數(shù)據(jù)資源添加上適合的鎖。此外數(shù)據(jù)庫(kù)還會(huì)維護(hù)這些鎖,當(dāng)一個(gè)資源上的鎖數(shù)目太多時(shí),自動(dòng)進(jìn)行鎖升級(jí)以提高系統(tǒng)的運(yùn)行性能,而這一過(guò)程對(duì)用戶來(lái)說(shuō)完全是透明的。
              ANSI/ISO SQL 92標(biāo)準(zhǔn)定義了4個(gè)等級(jí)的事務(wù)隔離級(jí)別,在相同數(shù)據(jù)環(huán)境下,使用相同的輸入,執(zhí)行相同的工作,根據(jù)不同的隔離級(jí)別,可以導(dǎo)致不同的結(jié)果。不同事務(wù)隔離級(jí)別能夠解決的數(shù)據(jù)并發(fā)問(wèn)題的能力是不同的。
                  表 1 事務(wù)隔離級(jí)別對(duì)并發(fā)問(wèn)題的解決情況 

          隔離級(jí)別

          臟讀

          不可

          重復(fù)讀

          幻象讀

          第一類丟失更新

          第二類丟失更新

          READ UNCOMMITED

          允許

          允許

          允許

          不允許

          允許

          READ COMMITTED

          不允許

          允許

          允許

          不允許

          允許

          REPEATABLE READ

          不允許

          不允許

          允許

          不允許

          不允許

          SERIALIZABLE

          不允許

          不允許

          不允許

          不允許

          不允許


             
          事務(wù)的隔離級(jí)別和數(shù)據(jù)庫(kù)并發(fā)性是對(duì)立的,兩者此增彼長(zhǎng)。一般來(lái)說(shuō),使用READ UNCOMMITED隔離級(jí)別的數(shù)據(jù)庫(kù)擁有最高的并發(fā)性和吞吐量,而使用SERIALIZABLE隔離級(jí)別的數(shù)據(jù)庫(kù)并發(fā)性最低。

              SQL 92定義READ UNCOMMITED主要是為了提供非阻塞讀的能力,Oracle雖然也支持READ UNCOMMITED,但它不支持臟讀,因?yàn)镺racle使用多版本機(jī)制徹底解決了在非阻塞讀時(shí)讀到臟數(shù)據(jù)的問(wèn)題并保證讀的一致性,所以,Oracle的READ COMMITTED隔離級(jí)別就已經(jīng)滿足了SQL 92標(biāo)準(zhǔn)的REPEATABLE READ隔離級(jí)別。

              SQL 92推薦使用REPEATABLE READ以保證數(shù)據(jù)的讀一致性,不過(guò)用戶可以根據(jù)應(yīng)用的需要選擇適合的隔離等級(jí)。

          posted on 2010-12-17 22:42 馮占科 閱讀(535) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 虞城县| 定边县| 泉州市| 行唐县| 卢湾区| 阜平县| 阳朔县| 吴堡县| 图们市| 子长县| 万盛区| 清涧县| 武冈市| 岗巴县| 盐源县| 三都| 衡水市| 铜陵市| 泰安市| 招远市| 海伦市| 鄂尔多斯市| 白山市| 大庆市| 东丽区| 铜川市| 长垣县| 翼城县| 安塞县| 郯城县| 印江| 潜山县| 永宁县| 钦州市| 延边| 孙吴县| 固始县| 腾冲县| 姜堰市| 临邑县| 武隆县|