国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > Oracle > 正文

在客戶端處理Oracle的數(shù)據(jù)行加鎖問題

2024-08-29 13:42:09
字體:
供稿:網(wǎng)友
數(shù)據(jù)的完整性和并發(fā)性:
  
  在網(wǎng)絡(luò)數(shù)據(jù)庫處理數(shù)據(jù)中,需要保證數(shù)據(jù)的完整性、多事務(wù)的并發(fā)性和數(shù)據(jù)的一致性。數(shù)據(jù)庫系統(tǒng)必須最大限度的保證數(shù)據(jù)內(nèi)容的有效性和合理性,使得數(shù)據(jù)合法與合理,即保證數(shù)據(jù)的完整性。 而網(wǎng)絡(luò)(多用戶)數(shù)據(jù)庫應(yīng)用系統(tǒng)中,通常都會(huì)碰到多個(gè)事務(wù)同時(shí)請(qǐng)求修改同一數(shù)據(jù)。數(shù)據(jù)庫的并發(fā)性處理保證數(shù)據(jù)庫系統(tǒng)據(jù)能夠合理有效地處理多個(gè)事務(wù)請(qǐng)求,在數(shù)據(jù)庫治理系統(tǒng)協(xié)調(diào)下,宏觀表現(xiàn)為并行處理,微觀為逐個(gè)串行處理,保證數(shù)據(jù)的一致性,從而避免數(shù)據(jù)處理中的 “臟”數(shù)據(jù)發(fā)生。在數(shù)據(jù)庫系統(tǒng)本身對(duì)數(shù)據(jù)的并發(fā)性和一致性有基本控制能力下,以O(shè)racle為例的關(guān)系數(shù)據(jù)庫系統(tǒng)已經(jīng)能保證數(shù)據(jù)的并發(fā)性能,而數(shù)據(jù)庫的應(yīng)用設(shè)計(jì)則需要以考慮數(shù)據(jù)在并發(fā)過程中的一致性為重點(diǎn)。一個(gè)簡(jiǎn)單的例子:甲乙同時(shí)從數(shù)據(jù)庫中讀出了一條相同的數(shù)據(jù)記錄。甲把數(shù)據(jù)作了修改,并且作了事務(wù)提交。(而乙此時(shí)并不知道數(shù)據(jù)已經(jīng)被修改了。)稱乙已經(jīng)讀出的數(shù)據(jù)為臟數(shù)據(jù),破壞了數(shù)據(jù)的一致性 , 為了保證數(shù)據(jù)的一致性,此時(shí)有必要對(duì)數(shù)據(jù)進(jìn)行加鎖。再例如:一銀行帳戶有¥6000, 此時(shí)甲要從中提出¥5000,而乙也同時(shí)要從中提出¥5000,雙方在不加鎖查詢時(shí),雙方均認(rèn)為可以提款,事實(shí)上肯定有一方的提交會(huì)失敗。原因是在最終事務(wù)提交時(shí),要對(duì)數(shù)據(jù)作了加鎖查詢效驗(yàn)處理。
  
 在客戶端處理Oracle的數(shù)據(jù)行加鎖問題(圖一)

  并發(fā)性和一致性 
  
  數(shù)據(jù)庫中的數(shù)據(jù)鎖 為了防止多個(gè)用戶事務(wù)交替操作數(shù)據(jù)庫對(duì)象,破壞性數(shù)據(jù)庫完整性,同時(shí)又要保證數(shù)據(jù)的并發(fā)性和一致性,數(shù)據(jù)庫治理系統(tǒng)一般提供了各種類型的封鎖機(jī)制,可以自動(dòng)為一個(gè)事務(wù)封鎖資源,而在事務(wù)不需要時(shí)自動(dòng)釋放。以使另一個(gè)需要獨(dú)占該資源的事務(wù)能夠繼續(xù)進(jìn)程,而不會(huì)造成事務(wù)死鎖。數(shù)據(jù)庫對(duì)象的封鎖完全能夠由數(shù)據(jù)庫系統(tǒng)自動(dòng)完成,ORACLE (一般情況數(shù)據(jù)庫)對(duì)加鎖有以下特征:A 多種封鎖模式.例如:系統(tǒng)表的轉(zhuǎn)有鎖,共享鎖。B 完備的自動(dòng)加/解鎖功能和釋放機(jī)制。C 用低級(jí)別的封鎖換取高級(jí)別的并發(fā)處理。D能夠在客戶端/服務(wù)器模式下自動(dòng)封鎖過程。Oracle 的主要封鎖類型有:
  A 數(shù)據(jù)鎖,用于封鎖表或表中的指定行.屬于數(shù)據(jù)操縱鎖,
  
  B 字典鎖,用于保護(hù)數(shù)據(jù)庫對(duì)象(表,索引)的創(chuàng)建維護(hù).屬于數(shù)據(jù)定義鎖
  
  C 內(nèi)部鎖。用于保護(hù)數(shù)據(jù)庫的內(nèi)部結(jié)構(gòu).
  
  正常情況下,為完成數(shù)據(jù)操縱,一般需要兩種級(jí)別的封鎖方式,封鎖整表或行封。通常只在熱備份數(shù)據(jù),時(shí)候,需要對(duì)整表進(jìn)行鎖定. 而應(yīng)用程序的事務(wù)處理通常是數(shù)據(jù)行的數(shù)據(jù)操縱語句:
  
  INSERT,
   UPDATE,
   DELETE,
   SELECT (FOR UPDATE)
  
  以上操作在執(zhí)行過程中,數(shù)據(jù)庫都會(huì)對(duì)相應(yīng)的行做數(shù)據(jù)行封鎖.
  
  一般情況下,只要行封事務(wù)不放棄封鎖, 此行就不可能被其他任何用戶的事務(wù)修改(部分語句,如SELECT仍然答應(yīng)不加鎖地讀出)。只有當(dāng)數(shù)據(jù)庫重新啟動(dòng),數(shù)據(jù)表空間離線/在線處理,當(dāng)事務(wù)正常提交、回滾時(shí),行封事務(wù)才能被自動(dòng)解除封鎖. (通常 ROLLBACK ,COMMIT 可以自動(dòng)解除行封鎖。)在表上的數(shù)據(jù)鎖的高低級(jí)別為:
  
   在客戶端處理Oracle的數(shù)據(jù)行加鎖問題(圖二)

  簡(jiǎn)單的SELECT 語句無任何鎖,INSERT, UPDATE, DELETE為行專有(RX),答應(yīng)在操作中多次修改這些行, 提交或回滾后自動(dòng)解除封鎖,
  
  SELECT (FOR UPDATE )為專有行的數(shù)據(jù)鎖.在應(yīng)用程序中使用最多.也是通常對(duì)數(shù)據(jù)行進(jìn)行控制的簡(jiǎn)單有效的方法。例如:在Windows95下,同時(shí)分別用兩個(gè)以上SQL*PLUS,以相同的用戶聯(lián)接Oracle Server相同的實(shí)例,在其中一個(gè)窗口下做Update/Delete中任意操作,只要沒有提交,均不影響其它窗口的不加鎖查詢,但是不可以再其它窗口下對(duì)同一條記錄作Update/Delete 操作,Insert沒有提交以前,其它操作均無效。只有當(dāng)一方事務(wù)完成(提交/回滾)以后立即釋放相應(yīng)資源,另一方申請(qǐng)的事務(wù)才能成功響應(yīng)。
  
  行鎖在應(yīng)用程序的注重事項(xiàng)
  在實(shí)際應(yīng)用中,可能由于一次事務(wù)提交的數(shù)據(jù)太多,造成數(shù)據(jù)加鎖時(shí)間太長(zhǎng),破壞了數(shù)據(jù)的并發(fā)共享特性。假如事務(wù)獨(dú)占了相應(yīng)的資源,沒有得到釋放,而另一個(gè)事務(wù)占有該事務(wù)的下一個(gè)資源,就有可能造成數(shù)據(jù)庫應(yīng)用系統(tǒng)死鎖。另外,假如在加鎖過程中,出現(xiàn)網(wǎng)絡(luò)中斷,客戶端掉電等突發(fā)問題,被加鎖的資源無法解鎖,其它應(yīng)用程序?qū)o法繼續(xù)獲得已經(jīng)被加鎖的資源,也可以出現(xiàn)死鎖. 通常只有DBA才能取消事務(wù)或通過數(shù)據(jù)表空間的在線/離線操作解除加鎖事務(wù)(通常大型應(yīng)用系統(tǒng)這樣做有一定的風(fēng)險(xiǎn))。假如在程序應(yīng)用中經(jīng)常出現(xiàn)這樣的問題,則造成應(yīng)用數(shù)據(jù)庫應(yīng)用系統(tǒng)無法正常工作。雖然這樣的情況在C/S程序的開發(fā)/應(yīng)用中并不經(jīng)常出現(xiàn),但是在應(yīng)用程序設(shè)計(jì)中都是應(yīng)該嚴(yán)格考慮的。
  
  常用的數(shù)據(jù)加鎖方法(以O(shè)RACLE 與PB連接為例)
  A 在客戶端編程方法:在客戶端的編程處理的方法最簡(jiǎn)單,調(diào)試也很直觀、方便。但是這種方法僅僅在中、小型網(wǎng)絡(luò)中可以使用。因?yàn)楫?dāng)網(wǎng)絡(luò)用戶數(shù)量增加,或應(yīng)用程序在客戶端應(yīng)用過程中意外中斷(死機(jī),退出),則可能造成數(shù)據(jù)行的死鎖。其他用戶無法正確獨(dú)占加鎖。但是實(shí)際應(yīng)用表明此種方法在網(wǎng)絡(luò)自身可靠性好、用戶數(shù)量不大時(shí)經(jīng)常被采納。
  
  下面是用PowerBuilder 與 ORACLE的數(shù)據(jù)聯(lián)結(jié)處理實(shí)例。
  
  /**********************************************************
  
  *變量:ls_goodscode , li_store_qty
  
  * 表:AMS.TAB_STORE_GOODSINFO
  
  *
  
  *功能:從庫存數(shù)中減去 2
  
  *
  
  **********************************************************/
  
  STRING ls_goodscode
  
  INTEGER li_stroe_qty
  
  ls_goodscode = sle_goodscode.text
  
  SELECT QTY
  
  INTO li_store_qty
  
  FROM AMS.TAB_STORE_GOODSINFO
  
  WHERE GOODS_NO = SUBSTR(:ls_goodscode , 1, 13)
  
  AND SERIAL_NO = SUBSTR(:ls_goodscode , 14, 4)
  
  FOR UPDATE NOWAITE ; // 對(duì)數(shù)據(jù)加鎖,不等待。
  
  if SQLCA.SQLCODE = 0 then // if _01
  
  if li_store_qty >=2 then // if _02
  
  UPDATE AMS.TAB_STORE_GOODSINFO
  
  SET QTY = :li_store_qty - 2
  
  WHERE GOODS_NO = SUBSTR(:ls_goodscode , 1, 13)
  
  AND SERIAL_NO = SUBSTR(:ls_goodscode , 14, 4);
  
  if SQLCA.SQLCODE = 0 then
  
  COMMIT ; // 成功提交
  
  else
  
  ROLLBACK ;// 及時(shí)回滾解鎖
  
  messagebox("系統(tǒng)提示", "庫存數(shù)量已經(jīng)不足!");
  
  end if
  
  else
  
  ROLLBACK;
  
  messagebox("系統(tǒng)提示", "庫存數(shù)量已經(jīng)不足!");
  
  end if // end if 02
  
  else //其中 ORA-00054: resource busy and acquire with NOWAIT specified
  
  ROLLBACK ;// 及時(shí)回滾解鎖
  
  messagebox("系統(tǒng)提示", "數(shù)據(jù)讀入有誤,請(qǐng)稍候再試!",stopsign! ok!);
  
  end if // end if 01
  
  //同時(shí)在當(dāng)前的FROM WINDOW中的CLOSEQUERY中顯示寫明ROLLBACK ;
  
  設(shè)計(jì)說明:當(dāng)?shù)谝痪銼ELECT完成以后,假如數(shù)據(jù)加鎖正確,則可以繼續(xù)工作,但是此時(shí)可能數(shù)據(jù)被別的應(yīng)用程序控制,則返回Oracle的錯(cuò)誤代碼:ORA-00054說明共享沖突。此句可以用一個(gè)有限的循環(huán)控制,但是一定要防止數(shù)據(jù)死鎖。同時(shí)為了保證萬無一失,在當(dāng)前FORM的關(guān)閉事件中顯示寫明回滾(ROLLBACK)。
  
  B 在客戶端按傳輸(Transaction )方法處理:將要提交的所有SQL任務(wù)作為多個(gè)子串傳送到服務(wù)器端,用動(dòng)態(tài)SQL方法在客戶端一次傳輸完成后,在服務(wù)器端一次執(zhí)行完成,只有當(dāng)事務(wù)執(zhí)行正確,才能提交, 否則回滾。這樣在執(zhí)行多個(gè)表操作提交時(shí),數(shù)據(jù)執(zhí)行加鎖的時(shí)間影響將大大減小。這樣極大程度的緩解了多表共享數(shù)據(jù)的加鎖問題。好處是不需要服務(wù)器端的調(diào)試,但是,編程調(diào)試過程復(fù)雜。但是實(shí)際效果與第一種方法基本一致。
  
  C 存儲(chǔ)過程方法:這種方法是直接調(diào)用服務(wù)器的存儲(chǔ)過程,所有的對(duì)Client端程序代碼可以大大減少,數(shù)據(jù)一致性,并發(fā)性,安全性都能得到保證。客戶端的異常通常不會(huì)影起數(shù)據(jù)的死鎖。
  
  下面是用POWERBUILDER 與 ORACLE的數(shù)據(jù)聯(lián)結(jié)處理實(shí)例。
  
  /**********************************************************
  
  *變量:ls_goodscode , li_store_qty
  
  * 表:AMS.TAB_STORE_GOODSINFO
  
  *
  
  *功能:從庫存數(shù)中減去 2
  
  *
  
  **********************************************************/
  
  STRING ls_goodscode
  
  INTEGER li_stroe_qty
  
  ls_goodscode = st.text
  
  if len(ls_goodscode) = 17 then
  
  DECLARE pstore_goods PROCEDURE FOR pd_store_goods(:ls_goodscode ) ;
  
  // 從庫存數(shù)中減去 2
  
  execute pstore_goods;
  
  if SQLCA.SLQCODE < 0 then
  
  ROLLBACK ;
  
  messagebox("系統(tǒng)提示", "數(shù)據(jù)操作有誤,請(qǐng)稍候再試!",stopsign! ok!);
  
  end if
  
  else
  
  messagebox("系統(tǒng)提示", "數(shù)據(jù)輸入有誤!",information!, ok!);
  
  end if
  
  //同時(shí)在當(dāng)前的FROM WINDOW中的CLOSEQUERY中顯示寫明ROLLBACK ;
  
  在服務(wù)器端
  
  -- procedure pd_store_goods
  
  create or replace procedure pd_store_goods ( ls_goodscode in varchar2 )
  
  IS
  
  ln_store_qty number(10) ;
  
  begin
  
  SELECT nvl(QTY, -1)
  
  INTO ln_store_qty
  
  FROM AMS.TAB_STORE_GOODS_INFO
  
  WHERE GOODS_NO = SUBSTR(ls_goodscode , 1, 13)
  
  AND SERIAL_NO = SUBSTR(ls_goodscode , 14, 4)
  
  FOR UPDATE NOWAIT;
  
  if ln_store_qty >= 2 then
  
  UPDATE AMS.TAB_STORE_GOODS_INFO
  
  SET QTY = ln_store_qty - 2
  
  WHERE GOODS_NO = SUBSTR(ls_goodscode , 1, 13)
  
  AND SERIAL_NO = SUBSTR(ls_goodscode , 14, 4);
  
  COMMIT ;
  
  else
  
  ROLLBACK ;
  
  RAISE_application_ERROR(-200002, 'store not enougth!');
  
  end if;
  
  EXCEPTION
  
  WHEN OTHERS THEN
  
  RAISE_APPLICATION_ERROR(-200001, 'store not SCUESSCULL!');
  
  end ;
  
  設(shè)計(jì)說明:首先在SQL*PLUS中運(yùn)行存儲(chǔ)過程,在PB的程序端調(diào)用。只有當(dāng)SELECT語句正常加鎖后, UPDATE語句才可以正常執(zhí)行。在由此可見在客戶端不知道存儲(chǔ)過程運(yùn)行的內(nèi)容,調(diào)試/維護(hù)工作較麻煩。但是,因?yàn)樗械倪\(yùn)行都在服務(wù)器端,基本可以忽略除服務(wù)器端以外的所有問題,如網(wǎng)絡(luò)的通暢,客戶端異常等等。實(shí)際應(yīng)用中對(duì)大型繁重的數(shù)據(jù)處理大多采用這樣的方法。
  
  注重與小結(jié):
  在Oracle的連接中,需要解釋的是數(shù)據(jù)行加鎖在同一個(gè)事務(wù)中是不可見的,但是執(zhí)行權(quán)限級(jí)別順序?yàn)椋篋elete >Update >Insert >Select.
  
  本文以O(shè)racle為例,說明在數(shù)據(jù)庫處理過程中,在數(shù)據(jù)庫設(shè)計(jì)上,要考慮數(shù)據(jù)的數(shù)據(jù)的完整性,在數(shù)據(jù)庫的應(yīng)用設(shè)計(jì)上必須著重事務(wù)的并發(fā)性和數(shù)據(jù)的一致性。對(duì)于數(shù)據(jù)行鎖要謹(jǐn)慎對(duì)待。
  


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 大厂| 阳信县| 江城| 大荔县| 巴彦淖尔市| 陈巴尔虎旗| 咸宁市| 泾川县| 武冈市| 灌云县| 昭觉县| 吴川市| 原阳县| 易门县| 吉安市| 台中县| 汤阴县| 禹城市| 临洮县| 清水河县| 那坡县| 莎车县| 白银市| 繁峙县| 留坝县| 台山市| 克东县| 甘肃省| 佳木斯市| 泾源县| 莎车县| 宜良县| 梁平县| 合川市| 琼结县| 陆河县| 绥滨县| 西平县| 沙雅县| 抚顺市| 昭平县|