陳秋月,張劍妹
(長治學(xué)院 計算機(jī)系,山西 長治 046011)
隨著企業(yè)信息化建設(shè)的不斷深入,關(guān)系數(shù)據(jù)庫管理系統(tǒng)(RDBMS)目前成為諸多公司和大型企業(yè)的核心IT系統(tǒng)。數(shù)據(jù)庫是一個允許多個用戶共享的數(shù)據(jù)資源,但當(dāng)多個用戶同時并發(fā)操作同一組數(shù)據(jù)時,就會損害數(shù)據(jù)庫的完整性和數(shù)據(jù)一致性。因此采用適當(dāng)?shù)姆椒▽τ趨f(xié)調(diào)多個事務(wù)并發(fā)操作,保證數(shù)據(jù)庫的完整性、正確性和一致性具有重要意義。
所謂事務(wù)是指用戶定義的一個數(shù)據(jù)庫操作序列,正確執(zhí)行的事務(wù)應(yīng)符合“ACID準(zhǔn)則”,即原子性、持續(xù)性、一致性和隔離性。
(1)原子性(Atomicity):事務(wù)中包括的諸多操作要么全部執(zhí)行,要么全部不執(zhí)行。
(2)持續(xù)性(Consistency):一個事務(wù)一旦提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變是永久性的。
(3)一致性(Isolation):任何數(shù)據(jù)庫事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫從一個一致的狀態(tài)轉(zhuǎn)變到另一個一致的狀態(tài)。
(4)隔離性(Durability):一個事務(wù)的執(zhí)行不能被其他事務(wù)所干擾。
多個事務(wù)如不加控制地并發(fā)執(zhí)行,則會產(chǎn)生數(shù)據(jù)的不一致,這些數(shù)據(jù)不一致主要包括丟失修改、不可重復(fù)度和讀“臟”數(shù)據(jù)等,如圖1所示。
圖1 三種數(shù)據(jù)不一致性
(1)丟失修改(Lost Update):兩個事務(wù)對同一數(shù)據(jù)并發(fā)地寫入,其執(zhí)行結(jié)果與串行地執(zhí)行兩個事務(wù)的結(jié)果不一致。
(2)不可重復(fù)讀(Unrepeatable Read):因讀 -寫沖突引起,結(jié)果可能導(dǎo)致第二次讀的值與前次讀的值不同。
(3)讀“臟”數(shù)據(jù)(Dirty Read):因一事務(wù)讀另一事務(wù)尚未提交的數(shù)據(jù)引起,有可能讀到要回退的數(shù)據(jù)。
產(chǎn)生上述三類數(shù)據(jù)不一致性的原因是并發(fā)操作破壞了事務(wù)的隔離性。因此,事務(wù)并發(fā)執(zhí)行時,通常采用封鎖技術(shù)來避免多用戶操作時數(shù)據(jù)的不一致。
所謂封鎖就是一個事務(wù)可以向系統(tǒng)申請對某數(shù)據(jù)對象加鎖,這樣事務(wù)就對該數(shù)據(jù)對象有了一定的控制權(quán)。
2.3.1 封鎖的粒度
封鎖粒度與系統(tǒng)的并發(fā)度和開銷密切相關(guān)。封鎖的粒度越大,并發(fā)度越低,系統(tǒng)開銷就越小;反之,封鎖的粒度越小,并發(fā)度就越高,但系統(tǒng)開銷也就越大。系統(tǒng)通常提供不同的封鎖粒度。鎖的粒度可以分為行、頁、鍵、盤區(qū)、表和數(shù)據(jù)庫。
2.3.2 封鎖的類型
常用的的封鎖類型有排它鎖(X鎖)和共享鎖(S鎖)。
(1)排它鎖:若事務(wù)T對數(shù)據(jù)A加上X鎖,則事務(wù)T可以讀取和修改A,其他事務(wù)不能再對A加任何類型的鎖,直到T釋放A上的X鎖。
圖2 使用封鎖機(jī)制解決三種數(shù)據(jù)不一致問題
(2)共享鎖:若事務(wù)T對數(shù)據(jù)對象A加上S鎖,則事務(wù)T可以讀A但不能修改A,其他事務(wù)只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。
圖2給出了使用封鎖機(jī)制來解決圖1中的數(shù)據(jù)不一致性問題。
關(guān)系數(shù)據(jù)庫并發(fā)控制的實(shí)現(xiàn)途徑有很多種,其中最常用的有以下幾種:調(diào)整用戶工作模式,修改應(yīng)用程序,避免不必要的并發(fā);設(shè)置隔離級別,盡量讓一個事務(wù)工作專一;調(diào)整應(yīng)用程序;利用開發(fā)工具的支持;借助于DBMS的功能。
這種方法適用于規(guī)模小、獨(dú)立性高、業(yè)務(wù)流程規(guī)范明確的系統(tǒng)。比如在圖書銷售系統(tǒng)中,只有銷售人員、庫管部門和銷售部門可以修改圖書數(shù)量。所以,在設(shè)計數(shù)據(jù)庫表時只需要在庫表中增加一個用戶列,在用戶操作時,把用戶列作為一個過濾條件,對應(yīng)用程序的SQL語句做相應(yīng)的調(diào)整。但是這種方法有其局限性,在分布式數(shù)據(jù)庫中,往往共享數(shù)據(jù)庫操作的客戶端比較多,這種情況下并發(fā)控制仍然是不可避免的。
隔離級別是事務(wù)準(zhǔn)備接受不一致數(shù)據(jù)的級別,是事務(wù)與其他事務(wù)進(jìn)行隔離的程度。當(dāng)多個事務(wù)同時進(jìn)行時,可以通過設(shè)置隔離級別來處理丟失修改、臟讀、不可重復(fù)讀。根據(jù)應(yīng)用程序的業(yè)務(wù)邏輯采用不同的隔離級別是很重要的,降低隔離級別可以增加事務(wù)的并發(fā)度,但是會影響數(shù)據(jù)的一致性;反之可以保證數(shù)據(jù)的一致性,但可能造成事務(wù)阻塞等,對并發(fā)產(chǎn)生負(fù)面影響。所以,在并發(fā)事務(wù)執(zhí)行過程中應(yīng)設(shè)置恰當(dāng)?shù)母綦x級別,盡量讓事務(wù)工作更專一。
有的關(guān)系數(shù)據(jù)庫系統(tǒng)并沒有提供并發(fā)控制的功能,例如Foxpro。在這種情況下要實(shí)現(xiàn)并發(fā)控制,通常需要在相應(yīng)的數(shù)據(jù)庫表中增加一個時間戳字段。當(dāng)用戶瀏覽記錄時先將時間戳值記到old_record(用戶的自定義變量)中,再將old_record中的內(nèi)容記錄到新記錄new_record中,當(dāng)用戶編輯new_record并提交時,比較old_record和原先的記錄中的時間戳,如果一樣,則表明沒有用戶修改原先的記錄,用new_record中的內(nèi)容替換時間戳中的內(nèi)容。反之則放棄修改。
目前,許多關(guān)系數(shù)據(jù)庫開發(fā)工具都具有一些方便的選項(xiàng)或部件來支持并發(fā)控制,如:Delphi和Powerbuilder。PowerBuilder中的并發(fā)控制技術(shù)主要通過設(shè)置Data Window的更新屬性來實(shí)現(xiàn)。其相關(guān)參數(shù) Key Columns、Key and Updateable Columns、Key and Modified Columns為關(guān)系數(shù)據(jù)庫的并發(fā)操作提供了很好的支持。通過Data Window,開發(fā)人員無需編寫復(fù)雜的SQL語句,就可以實(shí)現(xiàn)對數(shù)據(jù)庫的讀寫操作,這為數(shù)據(jù)庫系統(tǒng)開發(fā)節(jié)約了大量時間成本。
上面討論的幾種方法都能夠較好的提高RDBMS的并發(fā)性能,但操作對象都不是由RDBMS自己來提供支持的。一般大型RDBMS都提供了比較好的并發(fā)控制功能,其通常采用自定義事務(wù)隔離級別、顯式加鎖等方式。
充分利用RDBMS自身所支持的并發(fā)控制功能無疑是實(shí)現(xiàn)并發(fā)控制的最好途徑之一,而典型的關(guān)系數(shù)據(jù)庫系統(tǒng)Sybase SQL Server就提供了這方面的支持。
例如一網(wǎng)上圖書銷售系統(tǒng),同一時刻甲、乙兩地均有一客戶查詢到某圖書有剩余,并欲購買,此時如果該圖書只剩余了一本,那么問題就會產(chǎn)生:若甲客戶先買入圖書,則該圖書庫存就為零了,而乙客戶并不知道甲客戶已經(jīng)購買,繼續(xù)購買該圖書,結(jié)果將會導(dǎo)致“無書仍售”現(xiàn)象。
SQL Server支持的鎖類型包括:共享鎖、排它鎖、更新鎖、架構(gòu)鎖、意向鎖等。SQL Server會自動應(yīng)用正確的鎖類型保證多用戶環(huán)境下數(shù)據(jù)的一致性。對于“無書仍售”問題,我們可以在執(zhí)行銷售圖書后,在對圖書數(shù)目更新之前利用排它鎖查詢一下books表中現(xiàn)存的圖書數(shù)目。
SQL Server提供了4種隔離級別,用戶可以通過set transaction isolation level命令手工設(shè)置事務(wù)處理隔離層的鎖狀態(tài)。
(1)未提交讀(read uncommitted):當(dāng)設(shè)置該選項(xiàng)時,可以讀取到已由其他事務(wù)修改但還未提交的數(shù)據(jù)。
(2)提交讀(read committed):該選項(xiàng)是 SQL Server的默認(rèn)值。當(dāng)設(shè)置該選項(xiàng)時,只能讀取其他事務(wù)提交的數(shù)據(jù)。
(3)可重復(fù)讀(repeatable read):當(dāng)同一事物需要多次讀取同一數(shù)據(jù),且必須保證每次讀取的數(shù)據(jù)相同時使用,以防止其他用戶更新數(shù)據(jù)。
(4)可串行讀(serializable):是四個隔離級別中限制最大的級別,事物之間完全隔離。
實(shí)現(xiàn)關(guān)系數(shù)據(jù)庫并發(fā)控制的途徑很多,但無論什么方法依據(jù)的基本原則都是:確保數(shù)據(jù)庫數(shù)據(jù)的一致性和正確性,并在此基礎(chǔ)上盡量提高事務(wù)的并發(fā)度。
[1]王珊,薩師煊.數(shù)據(jù)庫系統(tǒng)概論(第四版)[M].北京:高等教育出版社,2006.
[2]胡百靜,姚巧玫.SQL Server 2005數(shù)據(jù)庫開發(fā)詳解[M].北京:電子工業(yè)出版社,2006.
[3]張劍妹.數(shù)據(jù)庫的并發(fā)控制[J].晉東南師專學(xué)報,1999,(3):50-52.
[4]錢學(xué)忠,黃向前.基于SQL Server的實(shí)用并發(fā)控制技術(shù)[J].江南大學(xué)學(xué)報,2003,(3):240-244.