程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> oracle事務特性詳解,oracle事務詳解

oracle事務特性詳解,oracle事務詳解

編輯:Oracle教程

oracle事務特性詳解,oracle事務詳解


原子性

事務是一個完整的操作。事務的各步操作是不可分的(原子的);要麼都執行,要麼都不執行。

-- 創建表
create table account_money
(
  id    number(4) not null,
  name  varchar2(4) not null,
  money number(5,2) not null
)
;
-- 增加一個檢查約束 
alter table account_money
  add constraint CK_money
  check (money>=0);

 

--向張三這個賬號增加數據
insert into ACCOUNT_MONEY (ID, NAME, MONEY)
values (1001, '張三', 500.00);
insert into ACCOUNT_MONEY (ID, NAME, MONEY)
values (1002, '張三', 1.00);

增加後的表如下:

       ID    NAME    MONEY
1    1001    張三    500.00   
2    1002    張三    1.00   

 

以下為oracle事務處理

BEGIN
  --從張三的1001賬戶轉入張三的1002賬戶
  UPDATE account_money a SET a.Money=a.Money-600 WHERE a.Id='1001';
  UPDATE account_money a SET a.Money=a.Money+600 WHERE a.Id='1002';
  COMMIT;--提交事務
EXCEPTION --異常處理
  WHEN OTHERS THEN ROLLBACK;--出現異常就回滾
  Dbms_Output.Put_Line('轉賬異常,轉賬失敗');  

在上述代碼中,因為賬戶設置了檢查約束,當賬戶小於0時,就會出現異常,如果不進行事務異常處理,那麼第二條更新語句會被執行。當做了事務異常處理後,當出現異常就會回滾。

一致性

在事務操作前後,數據必須處於一致狀態。是一個業務規則約束的范疇。

同樣使用以上的表來做以說明:

DECLARE
  account_a account_money.Money%TYPE;
  account_b account_money.Money%TYPE;
BEGIN
  SELECT a.money INTO account_a FROM account_money a WHERE a.Id='1001'; 
  SELECT a.money INTO account_b FROM account_money a WHERE a.Id='1002'; 
  Dbms_Output.Put_Line('轉賬前A賬戶余額:'||account_a);
  Dbms_Output.Put_Line('轉賬前B賬戶余額:'||account_b);
  Dbms_Output.Put_Line('轉賬前總余額:'||(account_a+account_b));
  UPDATE account_money SET money=money-100 WHERE ID='1001';
  UPDATE account_money SET money=money+100 WHERE ID='1002';
  COMMIT;
  SELECT a.money INTO account_a FROM account_money a WHERE a.Id='1001'; 
  SELECT a.money INTO account_b FROM account_money a WHERE a.Id='1002'; 
  Dbms_Output.Put_Line('轉賬後A賬戶余額:'||account_a);
  Dbms_Output.Put_Line('轉賬後B賬戶余額:'||account_b);
  Dbms_Output.Put_Line('轉賬後總余額:'||(account_a+account_b));
  EXCEPTION
    WHEN OTHERS THEN
      Dbms_Output.Put_Line('轉賬失敗,業務取消');
  SELECT a.money INTO account_a FROM account_money a WHERE a.Id='1001'; 
  SELECT a.money INTO account_b FROM account_money a WHERE a.Id='1002'; 
  Dbms_Output.Put_Line('停止轉賬後A賬戶余額:'||account_a);
  Dbms_Output.Put_Line('停止轉賬後B賬戶余額:'||account_b);
  Dbms_Output.Put_Line('停止轉賬後總余額:'||(account_a+account_b));
END;

 

 

執行上段代碼,

執行第一遍:

轉賬前A賬戶余額:500
轉賬前B賬戶余額:1
轉賬前總余額:501
轉賬後A賬戶余額:400
轉賬後B賬戶余額:101
轉賬後總余額:501


執行第二遍:

轉賬前A賬戶余額:400
轉賬前B賬戶余額:101
轉賬前總余額:501
轉賬後A賬戶余額:300
轉賬後B賬戶余額:201
轉賬後總余額:501

執行第三遍:

轉賬前A賬戶余額:300
轉賬前B賬戶余額:201
轉賬前總余額:501
轉賬後A賬戶余額:200
轉賬後B賬戶余額:301
轉賬後總余額:501

。。。。。。

當執行第5遍時:A賬戶的余額為0,如果再執行會出現象呢?

轉賬前A賬戶余額:100
轉賬前B賬戶余額:401
轉賬前總余額:501
轉賬後A賬戶余額:0
轉賬後B賬戶余額:501
轉賬後總余額:501

執行第6遍,第7遍…………:

轉賬前A賬戶余額:0
轉賬前B賬戶余額:501
轉賬前總余額:501
轉賬失敗,業務取消
停止轉賬後A賬戶余額:0
停止轉賬後B賬戶余額:501
停止轉賬後總余額:501

 

我們會發現,當我們做事務處理後,總額不會發生變化,當出現異常就不會再執行(或者說回滾)!

 

隔離性

對數據進行修改的所有並發事務是彼此隔離的,這表明事務必須是獨立的,它不是以任何方式依賴於或影響其它事務。

每個事務是獨立的,我們在PL/SQL中新建兩個SQL窗口就以可以做兩個事務處理。

我們還是使用以上表,表內容如下:

       ID    NAME    MONEY
1    1001    張三    0.00
2    1002    張三    501.00

第一個SQL窗口:

 

第二個SQL窗口:

輸入:SELECT * FROM account_money;這條查詢語句,我們會發現,第一個SQL窗口沒有執行之前的數據。

如果我們也在第二個SQL窗口使用update更新數據會怎麼樣呢?

UPDATE account_money SET money=money+300 WHERE ID='1001';
SELECT * FROM account_money;

他會等待第一個SQL窗口提交事務才會有更新結果!

這時我們提交第一個SQL窗口的事務,我們會看到,兩個窗口的結果都發生變化。

 

我們再提交第二個SQL窗口的事務(在第一個SQL窗口事務沒有提交之前是不能提交第二個窗口的事務的),結果也同上圖!

 

持久性

事務完成後,它對數據庫的修改被永久保存下來。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved