來自張健姿
>>>>>>>>>>>>
PowerBuilder應(yīng)用開發(fā)系列講座(4)
并發(fā)控制
華天新技術(shù)開發(fā)公司 張健姿
并發(fā)能力是指多用戶在同一時間對相同數(shù)據(jù)同時訪問的能力。一般的關(guān)系型數(shù)據(jù)庫都具有并發(fā)控制的能力,但是這種并發(fā)功能也會對數(shù)據(jù)的一致性帶來危險。試想若有兩個用戶都試圖訪問某個銀行用戶的記錄并同時要求修改該用戶的存款余額時,情況將會怎樣呢?我們可以對PowerBuilder中的DataWindow進(jìn)行設(shè)置來進(jìn)行并發(fā)控制。所謂并發(fā)控制就是指在用戶數(shù)據(jù)修改的過程中保證該數(shù)據(jù)不被覆蓋或改變的方式,在下面的例子中我們將看到如何設(shè)置Da taWindow來控制開發(fā)訪問。為了說明問題,我們舉這樣一個簡單的銀行系統(tǒng)中的例子,某用戶的存款狀況如右:
我們假設(shè)事情的經(jīng)過是這樣的:公司的某員工在銀行前臺取款2,000元,銀行出納查詢用戶的存款信息顯示銀行存款余額20,000元;正在這時,另一銀行帳戶轉(zhuǎn)帳支票支付該帳戶5,0 00元,機(jī)器查詢也得到當(dāng)前用戶存款20,000元,這時銀行的出納員看到用戶存款超過了取款額 ,就支付了客戶2,000元并將用戶存款改為18,000元,然后銀行的另一名操作員根據(jù)支票,將匯入的5,000元加上,把用戶的余額改為25,000元,那么數(shù)據(jù)庫管理系統(tǒng)是否可以接受這些修改呢?
在DataWindows的設(shè)計中,我們選擇菜單Rows|Update…,會出現(xiàn)Specify Update Charac teristics的設(shè)置窗口,在這個窗口中我們設(shè)置Update語句中Where子句的生成,以此來進(jìn)行開發(fā)控制。在這里有三個選項,我們分別看一看在本例中這三個選項的結(jié)果:
(1)Key Columns:生成的Where子句中只比較表中的主鍵列的值與最初查詢時是否相同來確定要修改的記錄。在上述的例子中,轉(zhuǎn)帳支票的操作將覆蓋出納員作出的修改,這樣銀行損失兩千元。
(2)Key and Updateable Columns:生成的Where子句比較表中主鍵列和可修改列的值與最初查詢時否是相同。在上例中兩次查詢出的結(jié)果都是有兩萬余額,當(dāng)?shù)谝粋€人修改余額時 ,余額仍是二萬元,所以修改成立,而支票轉(zhuǎn)帳操作時余額已不是二萬,所以該列不匹配,修改失敗。
(3)Key and Modified Columns:Where子句比較主鍵和將要修改的列,在本例中,結(jié)果與 Key and Updateable Columns的選擇相同,因?yàn)橛囝~已改變,不再與最初的查詢相同,因此仍然不能修改。
讓我們作另外一個假設(shè),我們把銀行后臺作支票轉(zhuǎn)帳操作改為凍結(jié)用戶存款,即把狀態(tài)字段的值改為凍結(jié),而且事件發(fā)生的次序如下表,那么表中的次序4…前臺出納的修改能不能成立呢:
1.Key Columns:Where子句只比較主鍵值,顯然出納員的修改是允許的。
2.Key and Updateable Columns:生成的Where子句包括比較所有可修改的列,因此出納修改時Statue字段為凍結(jié)與出納查詢時的tive不符,修改失敗,同時顯示錯誤信息。
3.Key and Modified Columns:Where子句的比較包括主鍵和要修改的列,由于本列中修改列仍為20,000元沒有變化,所以出納的修改可以成立。
在本例中,我們可以看到Key and Updateable Columns的選項最嚴(yán)格,可以避免出現(xiàn)狀態(tài)列發(fā)生改變時余額作修改的錯誤,但是這也會禁止我們作一些本當(dāng)允許的并發(fā)修改,如出納修改存款余額,而業(yè)務(wù)員修改用戶的聯(lián)系地址等。因此我們應(yīng)當(dāng)根據(jù)實(shí)際情況,選擇適當(dāng)?shù)腢pd ate設(shè)置。
根據(jù)我們使用數(shù)據(jù)庫的不同,我們還有一些其他的控制并發(fā)訪問和修改的選擇方案,如對數(shù)據(jù)加鎖。鎖是一個用戶避免其他用戶對指定行作修改的操作。在結(jié)束一個事務(wù)如執(zhí)行com mit,rollback,disconnect等語句時自動將鎖釋放。如果您使用的DBMS支持鎖的操作,在Pow er-Builder的DataWindow設(shè)計時,Select語句可在from子句中加上with holdlock:即在data Window的SQL Window中,在表窗口的標(biāo)題處點(diǎn)擊右鼠標(biāo),彈出菜單的最后一個選項即為Hold lock。選擇該項,生成的SQL語句將在re-trievel()函數(shù)執(zhí)行后將所查詢的數(shù)據(jù)加鎖,以避免其他用戶的修改訪問,直至commit,rollback等事件發(fā)生后解鎖。這種方式帶來的問題是,當(dāng)用戶查詢完數(shù)據(jù)后可能離開計算機(jī)長時間不用,這段時間內(nèi)其他用戶均無法修改數(shù)據(jù)。此外有些DBMS如Sybase等不支持行級鎖,也就是說當(dāng)你對某一行查詢時更多的行都被上了鎖,這就更增加了并發(fā)處理的局限性。另一個值得注意的問題是在多窗口應(yīng)用中某一個窗口的事務(wù)提交將會導(dǎo)致使用一事務(wù)中其他數(shù)據(jù)窗口的查詢行解鎖,這時修改將可能發(fā)生錯誤。某些DBMS 系統(tǒng)支持一個稱作"時間戳(timestamp)"的數(shù)據(jù)項來控制并發(fā)性。每張表中都有一個時間戳的數(shù)據(jù)列,當(dāng)Insert語句或Update語句對數(shù)據(jù)行作修改時該列自動被修改為當(dāng)前時間。當(dāng)你要作修改時,where子句可檢查時間戳列在查詢時和修改時兩個值是否相符,以此來確保您作出的修改不會覆蓋別人的修改,因此這種確認(rèn)方式與key and Updateable Columns選項相同。即使兩個用戶對同一行的不同列作修改,后一個修改者也將失敗。在常用的關(guān)系型數(shù)據(jù)庫中Sybase和Microsoft的SQL Server支持時間戳的使用。而在PowerBuilder中,不管用戶后臺連接何種數(shù)據(jù)庫,只要表中帶有timestamp的列名且數(shù)據(jù)類型為datetime,PB將自動忽略Upda te characteristics的選項,而在where子句中生成主鍵和時間戳列的比較。
如果您所用的數(shù)據(jù)庫不支持時間戳但支持觸發(fā)器,您也可以在表中增加一列整數(shù)型的列。當(dāng)有對表中某種記錄作修改時,該列自動加1。下列使用的是Watcom數(shù)據(jù)庫,對Shipper表增加Updcnt字段并作兩個觸發(fā)器,這樣任何用戶或進(jìn)程試圖修改某行記錄時,該字段均可發(fā)生變化。
對INSERT觸發(fā)器的編寫如下:
DROP TRIGGER INS—SHIPPER’
CREATE TRIGGER SHIPPER BEFORE INSERT ON SHIPPER
REFERENCING NEW AS Newvalue
FOR EACH ROW
BEGIN
SET newvalue.UpdCnt=newvalue.UpdCnt+1;
END‘
同理可編寫UPDATE觸發(fā)器。
在您的PowerBuilder應(yīng)用之中,除表的主鍵外,必須再加上這一列作為檢測列加入Updat e語句中的Where子句中,這樣再作Update操作時,后臺數(shù)據(jù)庫會比較修改時與用戶作Retriev e操作時數(shù)據(jù)是否相等,以確認(rèn)是否能作修改。在DataWindows中在Specify Update Charact eris-tics的對話框的右下角的Unique key column(s)中加上Updcnt一項,同時注意where c lause中選擇Key columns,這樣PowerBuilder在構(gòu)造where子句時就會認(rèn)為Updcnt亦是表的主鍵,而成為檢測項。
當(dāng)數(shù)據(jù)窗口的Update函數(shù)被調(diào)用后,觸發(fā)器將修改過記錄中的Updcnt列表為新值,為保證下一次修改能夠有效,您應(yīng)當(dāng)立即作Retrieve()以使DataWindow緩沖區(qū)中Updcnt的值與數(shù)據(jù)庫相同。顯然修改后立即查詢的代價要比其他任何一種并
發(fā)控制的代價要小得多。