明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

SQL Server與Oracle防范數(shù)據(jù)鎖定的比較

[摘要]廖錚 2002-5-30 14:23:50-------------------------------------------------------------------------------- 數(shù)據(jù)庫(kù)并行訪問(wèn),也就是兩個(gè)或兩以上用戶同時(shí)訪問(wèn)同一數(shù)據(jù),這也是數(shù)據(jù)庫(kù)引擎如何設(shè)計(jì)和實(shí)現(xiàn)適度反應(yīng)...
廖錚

2002-5-30 14:23:50

--------------------------------------------------------------------------------


數(shù)據(jù)庫(kù)并行訪問(wèn),也就是兩個(gè)或兩以上用戶同時(shí)訪問(wèn)同一數(shù)據(jù),這也是數(shù)據(jù)庫(kù)引擎如何設(shè)計(jì)和實(shí)現(xiàn)適度反應(yīng)所面臨的最大問(wèn)題。設(shè)計(jì)優(yōu)良、性能卓越的數(shù)據(jù)庫(kù)引擎可以輕松地同時(shí)為成千上萬(wàn)的用戶服務(wù)。而“底氣不足”的數(shù)據(jù)庫(kù)系統(tǒng)隨著更多的用戶同時(shí)訪問(wèn)系統(tǒng)將大大降低其性能。最糟糕的情況下甚至可能導(dǎo)致系統(tǒng)的崩潰。

當(dāng)然,并行訪問(wèn)是任何數(shù)據(jù)庫(kù)解決方案都最為重視的問(wèn)題了,為了解決并行訪問(wèn)方面的問(wèn)題各類數(shù)據(jù)庫(kù)系統(tǒng)提出了各種各樣的方案。 SQL Server和Oracle兩大DBMS也分別采用了不同的并行處理方法。它們之間的實(shí)質(zhì)差別在哪里呢?

并行訪問(wèn)的問(wèn)題
并行訪問(wèn)出現(xiàn)問(wèn)題存在若干種情況。在最簡(jiǎn)單的情形下,數(shù)量超過(guò)一個(gè)的用戶可能同時(shí)查詢同一數(shù)據(jù)。就這種情況而言數(shù)據(jù)庫(kù)的操作目標(biāo)很簡(jiǎn)單:盡可能地為用戶們提供快速的數(shù)據(jù)訪問(wèn)。 這對(duì)我們現(xiàn)在常見(jiàn)的數(shù)據(jù)庫(kù)來(lái)說(shuō)不成問(wèn)題:SQL Server和 Oracle 都采用了多線程機(jī)制,它們當(dāng)然能夠一次處理多個(gè)請(qǐng)求。

不過(guò),在用戶修改數(shù)據(jù)的情況下并行訪問(wèn)問(wèn)題就變得復(fù)雜起來(lái)了。顯然,數(shù)據(jù)庫(kù)通常只允許唯一用戶一次修改特定的數(shù)據(jù)。當(dāng)某一用戶開(kāi)始修改某塊數(shù)據(jù)時(shí), SQL Server和 Oracle 都能很快地鎖定數(shù)據(jù),阻止其他用戶對(duì)這塊數(shù)據(jù)進(jìn)行更新,直到修改該數(shù)據(jù)的第1位用戶完成其操作并提交交易(commit transaction)。但是,當(dāng)某一位用戶正在修改某塊數(shù)據(jù)時(shí)假設(shè)另一位用戶又正想查詢?cè)摂?shù)據(jù)的信息時(shí)會(huì)發(fā)生什么情況呢?在這種情況下數(shù)據(jù)庫(kù)管理系統(tǒng)又該如何動(dòng)作呢?Oracle 和 SQL Server針對(duì)這一問(wèn)題采取了不同的解決方案。

SQL Server方法
現(xiàn)在不妨假設(shè)有人開(kāi)始修改SQL Server上存儲(chǔ)的數(shù)據(jù),于是這塊數(shù)據(jù)立即被數(shù)據(jù)庫(kù)鎖定。數(shù)據(jù)鎖定操作阻塞其他任何訪問(wèn)該數(shù)據(jù)的連接——連查詢操作都不會(huì)放過(guò)。于是,這塊被鎖定的數(shù)據(jù)只有在交易被提交或者回滾之后才能接受其他訪問(wèn)操作。

下面用SQL Server隨帶的pubs示例數(shù)據(jù)庫(kù)做一個(gè)簡(jiǎn)單示范。在Query Analyzer內(nèi)打開(kāi)兩個(gè)窗口。在第1個(gè)窗口中執(zhí)行下列SQL操作語(yǔ)句,更新pubs數(shù)據(jù)庫(kù)中某一圖書(shū)的價(jià)格:

use pubs
go
begin tran
update titles
set price = price * 1.05
where

title_id = 'BU2075'

由于代碼中并沒(méi)有執(zhí)行commit語(yǔ)句,所以數(shù)據(jù)變動(dòng)操作實(shí)際上還沒(méi)有最終完成。接下來(lái),在另一個(gè)窗口里執(zhí)行下列語(yǔ)句查詢titles數(shù)據(jù)表:
select title_id,title,price
from titles
order by title_id.

你什么結(jié)果也得不到。窗口底部的小地球圖標(biāo)會(huì)轉(zhuǎn)個(gè)不停。盡管我在先前的操作中僅僅更新了一行,但是,select語(yǔ)句的執(zhí)行對(duì)象卻恰好包含了其數(shù)據(jù)正被修改的一行。因此,上面的操作不會(huì)返回任何數(shù)據(jù),除非回到第1個(gè)窗口提交交易或者回滾。

SQL Server的數(shù)據(jù)鎖定方案可能會(huì)降低系統(tǒng)的性能和效率。數(shù)據(jù)被鎖定的時(shí)間越長(zhǎng),或者鎖定的數(shù)據(jù)量越大,其他數(shù)據(jù)訪問(wèn)用戶就越可能不得不等待其查詢語(yǔ)句的執(zhí)行。因此,從程序員的角度來(lái)看,對(duì)SQL Server編程的時(shí)候應(yīng)該盡量地把交易代碼設(shè)計(jì)得既小又快。

在SQL Server的最近版本中,微軟對(duì)SQL Server進(jìn)行了某些修改,使其一次鎖定的數(shù)據(jù)量大大減少,這是數(shù)據(jù)庫(kù)設(shè)計(jì)中的一大重要改進(jìn)。在6.5版及以前版本中,最少的數(shù)據(jù)鎖定量是一頁(yè)。哪怕你只在修改一行數(shù)據(jù),而該行數(shù)據(jù)位于包含10行數(shù)據(jù)的一頁(yè)上,則整頁(yè)10行數(shù)據(jù)都會(huì)被鎖定。顯然,這么大的數(shù)據(jù)鎖定量增加了其他數(shù)據(jù)訪問(wèn)連接不得不等待數(shù)據(jù)修正完成的概率。在SQL Server 7中,微軟引入了行鎖定技術(shù),這樣,目前的SQL Server只鎖定實(shí)際正被改變的數(shù)據(jù)行。

SQL Server的解決方案聽(tīng)起來(lái)很簡(jiǎn)單,但實(shí)際上其幕后為提供足夠的系統(tǒng)高性能而采取了很多措施。例如,如果你在同時(shí)修改多行數(shù)據(jù),SQL Server則會(huì)把數(shù)據(jù)鎖定范圍提升到頁(yè)級(jí)別乃至鎖定整個(gè)數(shù)據(jù)表,從而不必針對(duì)每一記錄跟蹤和維護(hù)各自的數(shù)據(jù)鎖。

Oracle方法
下面我們?cè)倏纯碠racle數(shù)據(jù)庫(kù)是如何實(shí)施類似操作的。首先,我打開(kāi)一個(gè)SQLPlus實(shí)例執(zhí)行下列查詢語(yǔ)句(這個(gè)例子可以在Oracle 9i中示例中找到)。這個(gè)實(shí)例稱做查詢實(shí)例:
select first_name, last_name, salary
from hr.employees
where
department_id = 20;
代碼返回兩行數(shù)據(jù),如下所示:

然后,再打開(kāi)另一個(gè)SQLPlus實(shí)例——更新實(shí)例來(lái)執(zhí)行以下命令:
SQL> update hr.employees
2 set salary = salary * 1.05
3 where
4 department_id = 20
5 /
代碼執(zhí)行后回復(fù)消息稱兩行數(shù)據(jù)已被更新。
注意,以上代碼中并每有像在SQL Server示例那樣鍵入“begin tran”字樣的代碼。Oracle 的SQLPlus隱含啟用交易(你還可以模仿SQL Server的行為,設(shè)置“autocommit to on”自動(dòng)地提交交易)。接下來(lái)我們?cè)赟QLPlus更新實(shí)例中再執(zhí)行同查詢實(shí)例一樣的select語(yǔ)句。

結(jié)果清楚地表明:Michael和Pat的薪水都增加了,然而這個(gè)時(shí)候我還沒(méi)有提交數(shù)據(jù)變更交易。
現(xiàn)在轉(zhuǎn)到第1個(gè)SQLPlus查詢實(shí)例重新運(yùn)行查詢,結(jié)果如下:

Oracle不需要用戶等待數(shù)據(jù)更新實(shí)例中操作被提交,它徑直返回Michael和Pat的查詢信息,但實(shí)際上返回的是數(shù)據(jù)更新開(kāi)始之前的數(shù)據(jù)視圖!

這時(shí)候,熟悉SQL Server的人可能會(huì)說(shuō)了,在查詢中設(shè)置(NOLOCK)不也能達(dá)到同樣的效果嗎?可是,對(duì)SQL Server而言,在數(shù)據(jù)映像之前是不能獲取數(shù)據(jù)的。指定(NOLOCK)實(shí)際上只是得到了沒(méi)有提交的數(shù)據(jù)。Oracle的方法則提供了數(shù)據(jù)的一致視圖,所有的信息都是針對(duì)交易的、基于存儲(chǔ)數(shù)據(jù)快照的。

如果在SQLPlus的更新實(shí)例中提交更新交易在查詢實(shí)例中就能看到薪水?dāng)?shù)據(jù)發(fā)生變化。如果在查詢實(shí)例中重新運(yùn)行先前的查詢語(yǔ)句,那么Oracle將返回新的薪水?dāng)?shù)值。

存儲(chǔ)數(shù)據(jù)快照
說(shuō)了半天,在給用戶顯示先前版本的數(shù)據(jù)同時(shí),Oracle是如何允許其他用戶修改數(shù)據(jù)的呢?其實(shí),只要某一用戶啟動(dòng)了一宗修改數(shù)據(jù)的交易,之前的數(shù)據(jù)映像就會(huì)被寫(xiě)到一個(gè)特殊的存儲(chǔ)區(qū)域。這種“前映像”用來(lái)向任何查詢數(shù)據(jù)的用戶提供一致的數(shù)據(jù)庫(kù)視圖。這樣,當(dāng)其他用戶在修改數(shù)據(jù)的時(shí)候,在以上的測(cè)試中我們就能看到尚未發(fā)生變更的薪金數(shù)據(jù)。

這個(gè)特殊的存儲(chǔ)區(qū)域在哪里呢?這個(gè)問(wèn)題的答案就跟你正在使用的Oracle版本有關(guān)了。在 Oracle 8i及其以前版本中會(huì)為這一目的創(chuàng)建特殊的回滾段。然而,這種舉措會(huì)給數(shù)據(jù)庫(kù)管理員(DBA)帶來(lái)管理和調(diào)整數(shù)據(jù)段的工作負(fù)擔(dān)。例如,DBA必須確定為此需要的數(shù)據(jù)段的數(shù)量以及大小等。假如回滾段沒(méi)有正確配置,那么對(duì)交易而言它們就可能不得不排隊(duì)等待回滾段中出現(xiàn)必要的數(shù)據(jù)空間。

Oracle 9i就不同了,這是Oracle的最新版本,Oracle實(shí)現(xiàn)了一種新特性,這就是所謂的undo表空間,它有效地消除了以上的管理復(fù)雜性。雖然回滾段仍然可以繼續(xù)使用,但是,DBA現(xiàn)在可以選擇創(chuàng)建undo表空間的方式令Oracle自己管理“前映像”的復(fù)雜空間分配。
Oracle的這種方法對(duì)程序員具有重要意義。因?yàn)榛貪L空間不是無(wú)限的,所以,更新交易的數(shù)據(jù)快照會(huì)取代先前交易的映像。因此,如果必要的回滾段被其他交易的映像覆蓋的話。運(yùn)行時(shí)間較長(zhǎng)的查詢操作就可能產(chǎn)生“ snapshot too old”錯(cuò)誤。

下面舉個(gè)可能發(fā)生的案例。假設(shè)在上午11:59的時(shí)候某位職員開(kāi)始更新John Doe帳務(wù)的交易。這宗交易在下午12:01被提交。同時(shí),下午12:00某財(cái)務(wù)經(jīng)理開(kāi)始查詢所有的客戶帳務(wù)報(bào)表和當(dāng)月收費(fèi)總計(jì)。因?yàn)榭蛻艉芏,所以這一查詢操作很費(fèi)了點(diǎn)時(shí)間,但是不論這次操作到底執(zhí)行了多久,反正它檢索出的結(jié)果就是下午12:00數(shù)據(jù)庫(kù)中存在的數(shù)據(jù)。如果包含John Doe帳務(wù)前映像的回滾空間在查詢執(zhí)行到該客戶名字的時(shí)候被覆蓋則查詢返回錯(cuò)誤消息。
Oracle的解決方案當(dāng)然更為合理,在抽象意義上提供了相比SQL Server更佳的數(shù)據(jù)一致性。在執(zhí)行Oracle查詢的時(shí)候無(wú)須擔(dān)心較長(zhǎng)的查詢操作會(huì)鎖定重要的交易。但是,在兩種數(shù)據(jù)庫(kù)同時(shí)支持海量用戶的情況下也很難證明Oracle是否就能真正實(shí)現(xiàn)具體條件下的數(shù)據(jù)一致性。