淺談oracle事務


  所謂事務,他是一個操作序列,這些操作要么都執行,要么都不執行,是一個不可分割的工作單元。通俗解釋就是事務是把很多事情當成一件事情來完成,也就是大家都在一條船上,要死一起死,要活一起活。

  為什么要引入事務?事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向數據的資源。通過將一組相關操作組合為一個要么全部成功要么全部失敗的單元,可以簡化錯誤恢復並使應用程序更加可靠。事務結束后,能保證數據庫數據的一致性。例如銀行轉賬,一個賬號扣錢,一個賬號增款,要么都執行,要么都不執行,不能只執行一條,否則會出現賬款錯誤。這樣我們就可以體會到事務的重要性了吧。其實在我們的生活中,很多事情都是要組成事務來執行的。既然它那么重要,下面我們就來深入的了解一下什么是事務吧。

一.事務的四個特征ACID

  事務的四個特征非常重要,只有滿足這些特征,才能保證事務執行后只有一個結果:要么成功,要么失敗。

  (1)原子性(Atomicity):組成事務處理的語句形成了一個邏輯單元,不能只執行其中的一部分。

  (2)一致性(Consistemcy):事務處理前后,數據處於一致狀態,保證數據的無損。

  (3)隔離性(Isolation):對數據進行修改的多個事務是彼此隔離的,互不影響。

  (4)持久性(Durability):事務完成之后,它對於系統的影響是永久的,該修改即使出現系統故障也將一直保留,真實的修改了數據庫。

  示例一

---------創建表
CREATE TABLE bank
(
    customerName CHAR(10),          --顧客姓名
    currentMoney number(10)         --當前余額
);
---------添加余額不能小於1的約束
ALTER TABLE bank ADD CONSTRAINT CK_currentMoney CHECK(currentMoney >= 1);
---------插入測試數據
INSERT INTO bank(customerName, currentMoney) VALUES('張三', 1000);
INSERT INTO bank(customerName, currentMoney) VALUES('李四', 1);
commit;
select * from bank;
---------不使用事務完成轉帳操作(總金額異常)
    update bank set currentMoney=currentMoney-1000 where customerName='張三';
    update bank set currentMoney=currentMoney+1000 where customerName='李四';
commit;
---------清空數據,
delete bank;
select * from bank;
---------使用事務完成轉賬操作不會出現總金額異常
set serveroutput on;
declare
 li_money number(10):=0;
begin
  update bank set currentMoney=currentMoney+1000 where customerName='李四';
  select currentMoney into li_money  from bank where customerName='李四';
   dbms_output.put_line('李四當前的余額是:'||li_money);
  update bank set currentMoney=currentMoney-1000 where customerName='張三';
exception
  when others then
    dbms_output.put_line('撤銷提交');
    rollback;
end;
--轉帳之后查看結果,李四的錢被回滾回去了
select * from bank;

 

二.回滾到保存點

  (1)rollback:回滾到最初狀態,可以參考示例一。

  (2)rollback to 保留點:回滾到保留點。

  示例二

declare
  num int;
begin
  savepoint a; --創建保存點a
  update bank set currentmoney=currentmoney-100 where customername='張三';
  savepoint b; --創建保存點b
  update bank set currentmoney=currentmoney+100 where  customername='李四';
  savepoint c; --創建保存點c
  num:=# --從提示框接收一個數據,用於操作回滾到哪一點。
  insert into bank values('王五',600);
  savepoint d; --創建保存點d
  if num=1 then 
    rollback to a; --當提示框中輸入1時,回滾到保存點a,即全部回滾,相當於rollback;
  elsif num=2 then 
    rollback to b; --當提示框中輸入2時,回滾到保存點b
  elsif num=3 then 
    rollback to c; --當提示框中輸入3時,回滾到保存點c
  else 
    rollback to d; --其他情況下,回滾到保存點d
  end if;
end;

 

三.事務的隔離級別

  從上面的示例中我們可以看到事務帶給我們的巨大好處,保證了數據的一致性,但是,僅僅有保證用事務執行就可以保證數據前后是一致的嗎?在實際情況下,事務是並發執行的,不可避免的會出現多個事務同一時間對相同數據的操作,這樣就會產生各種並發問題。

  並發問題:(1)臟讀:事務T1、T2,T1讀取了T2已經更改但還沒有提交的數據,之后,若T2回滾,T1讀到的數據就是臨時無效的臟數據。

        (2)不可重復讀:事務T1、T2,T1讀取了一個字段,然后T2更新了該字段,當T1再次讀取該字段時,值就不同了。

        (3)幻讀:事務T1、T2,T1讀取了一個字段,T2在在該表中又插入了一些字段,當T1再次讀取時,會多出幾行。

  為了解決上面這些問題,引入了隔離級別,顯然,隔離級別是指一個事務與其他事務的隔離程度,隔離級別都有哪些呢,下面簡單介紹了一下。

隔離級別 描述
read uncommitted(讀取未提交數據) 允許事務讀取未被其他事務提交的變更,臟讀、不可重復讀和幻讀問題都會出現。
read committed(讀取已提交數據) 只允許事務讀取已被其他事務提交的變更,可以避免臟讀,但不可重復讀和幻讀問題仍然存在。
repeatable committed(可重復讀) 確保一個事務可以多次從一個字段中讀取到相同的值,避免了臟讀、不可重復讀,但幻讀問題仍然存在。
serializble(串行化) 在這個事務執行期間,禁止其他表對該表的插入、刪除、修改操作,所有並發問題都可以避免,但性能低下。

 

 

 

 

 

    Oracle 支持的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE。在 Oracle 默認的事務隔離級別為: READ COMMITED。Oracle同時提供了一個Read only的隔離級別。
  雖然隔離級別可以避免並發問題,但是要酌情使用,畢竟隔離級別越高,並發性就越弱,這樣軟件的性能就降低了。
四.總結
  (1)事務只有一個執行結果,要么成功,要么失敗。
  (2)事務的四個特點:原子性、一致性、隔離性和持續性。
  (3)事務的執行過程中發生問題時,可以直接回滾到最初未執行之前的數據狀態,也可以通過savepoint設置保存點,回滾到特定的保存點位置。
  (4)當多個事務同時訪問相同數據時,可能產生並發問題,為了避免這些問題,引入了隔離級別。但是隔離級別越高,雖然數據一致性越好,但是並發性卻更弱。所以要酌情使用。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM