Oracle事務(wù)(transaction)詳解
一、數(shù)據(jù)異常
因?yàn)镺racle中支持多個事務(wù)并發(fā)執(zhí)行,所以會出現(xiàn)下面的數(shù)據(jù)異常。
- 臟讀(Dirty Read):事務(wù)T1更新了一行數(shù)據(jù),還沒有提交所做的修改,T2讀取更新后的數(shù)據(jù),T1回滾,T2讀取的數(shù)據(jù)無效,這種數(shù)據(jù)稱為臟讀數(shù)據(jù)。
- 不可重復(fù)讀(UNrepeatable Read):事務(wù)T1讀取一行數(shù)據(jù),T2修改了T1剛剛讀取的記錄,T1再次查詢,發(fā)現(xiàn)與第一次讀取的記錄不相同,稱為不可重復(fù)讀。
- 幻讀(Phantom Read):事務(wù)T1讀取一條帶WHERE條件的語句,返回結(jié)果集,T2插入一條新紀(jì)錄,恰好也是T1的WHERE條件,T1再次查詢,結(jié)果集中又看到T2的記錄,新紀(jì)錄就叫做幻讀。
事務(wù)中遇到的這些異常與事務(wù)的隔離性設(shè)置有關(guān),事務(wù)的隔離性設(shè)置越多,異常就出現(xiàn)的越少,但并發(fā)效果就越低,事務(wù)的隔離性設(shè)置越少,異常出現(xiàn)的越多,并發(fā)效果越高。
二、隔離級別:
針對讀取數(shù)據(jù)時可能產(chǎn)生的不一致現(xiàn)象,在SQL92標(biāo)準(zhǔn)中定義了4個事務(wù)的隔離級別:
- NO_TRANSACTION 不支持事務(wù)
- READ_UNCOMMITED 允許臟讀、不可重復(fù)讀、幻讀
- READ_COMMITED 允許不可重復(fù)讀、幻讀,不允許臟讀
- REPEATABLE 允許幻讀,不允許臟讀、不可重復(fù)讀
- SERIALIZABLE 臟讀、不可重復(fù)讀、幻讀都不允許
Oracle默認(rèn)的隔離級別是read committed。
Oracle支持SQL92標(biāo)準(zhǔn)的READ_COMMITED、SERIALIZABLE,自身特有的Read only和Read write隔離級別。
- Read only:事務(wù)中不能有任何修改數(shù)據(jù)庫中數(shù)據(jù)的操作語句,是Serializable的一個子集。
- Read write:它是默認(rèn)設(shè)置,該選項(xiàng)表示在事務(wù)中可以有訪問語句、修改語句,但不經(jīng)常使用。
1、設(shè)置隔離級別
設(shè)置一個事務(wù)的隔離級別:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE;
注意:這些語句是互斥的,不能同時設(shè)置兩個或兩個以上的選項(xiàng)。
設(shè)置單個會話的隔離級別:
ALTER SESSION SET TRANSACTION ISOLATION LEVEL READ COMMITTED; ALTER SESSION SET TRANSACTION ISOLATION SERIALIZABLE;
三、數(shù)據(jù)庫鎖:
在數(shù)據(jù)庫中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)。
- 排它鎖:(X鎖,eXclusive Locks)
當(dāng)有DML語句執(zhí)行的時候,設(shè)計(jì)的行都會加上排它鎖,其他事物不能進(jìn)行讀取修改。 - 共享鎖:(S鎖,Shared Locks)
加了共享鎖的數(shù)據(jù),可以被其他事物讀取,但不能修改。如select語句。
為了保證性能:樂觀鎖,悲觀鎖
- 悲觀鎖:每次都是假設(shè)數(shù)據(jù)肯定會沖突,數(shù)據(jù)開始讀取時就把數(shù)據(jù)給鎖住。
- 樂觀鎖:每次都是假設(shè)一般情況下不會發(fā)生數(shù)據(jù)沖突,只有數(shù)據(jù)更新提交的時候,才會對數(shù)據(jù)的沖突與否進(jìn)行檢測,如果發(fā)生沖突,返回錯誤信息讓用戶處理。
在Oracle中最主要的鎖是DML鎖(data locks,數(shù)據(jù)鎖),DML鎖的目的在于保證并發(fā)情況下的數(shù)據(jù)完整性。在Oracle數(shù)據(jù)庫中,DML鎖主要包括TM鎖和TX鎖,其中TM鎖稱為表級鎖,TX鎖稱為事務(wù)鎖或行級鎖。
1、Oracle中的鎖
鎖有“共享鎖”、“排它鎖”,“共享排它鎖”等多種類型,而且每種類型又有“行級鎖” (一次鎖住一條記錄),“頁級鎖” (一次鎖住一頁,即數(shù)據(jù)庫中存儲記錄的最小可分配單元),“表級鎖” (鎖住整個表)。
(1)共享鎖(S鎖)
添加該S鎖。在該鎖定模式下,不允許任何用戶更新表。但是允許其他用戶發(fā)出select …from for update命令對表添加RS鎖。
lock table in share mode
(2)排他鎖(X鎖)
添加X鎖。在該鎖定模式下,其他用戶不能對表進(jìn)行任何的DML和DDL操作,該表上只能進(jìn)行查詢。
lock table in exclusive mode
(3)行級共享鎖(RS鎖)
通常是通過語句添加的,同時該方法也是我們用來手工鎖定某些記錄的主要方法。比如,當(dāng)我們在查詢某些記錄的過程中,不希望其他用戶對查詢的記錄進(jìn)行更新操作,則可以發(fā)出這樣的語句。當(dāng)數(shù)據(jù)使用完畢以后,直接發(fā)出rollback命令將鎖定解除。當(dāng)表上添加了RS鎖定以后,不允許其他事務(wù)對相同的表添加排他鎖,但是允許其他的事務(wù)通過DML語句或lock命令鎖定相同表里的其他數(shù)據(jù)行。
select … from for update
(4)行級排他鎖(RX鎖)
當(dāng)進(jìn)行DML操作時會自動在被更新的表上添加RX鎖,或者也可以通過執(zhí)行l(wèi)ock命令顯式的在表上添加RX鎖。在該鎖定模式下,允許其他的事務(wù)通過DML語句修改相同表里的其他數(shù)據(jù)行,或通過lock命令對相同表添加RX鎖定,但是不允許其他事務(wù)對相同的表添加排他鎖(X鎖)。
(5)共享行級排他鎖(SRX鎖)
添加SRX鎖。該鎖定模式比行級排他鎖和共享鎖的級別都要高,這時不能對相同的表進(jìn)行DML操作,也不能添加共享鎖。
lock table in share row exclusive mode
上述幾種鎖模式中,RS鎖是限制最少的鎖,X鎖是限制最多的鎖。當(dāng)程序?qū)λ龅男薷倪M(jìn)行提交(Commit)或回滾(Rollback)后,鎖住的資源便會得到釋放,從而允許其他用戶進(jìn)行操作。如果兩個事務(wù),分別鎖定一部分?jǐn)?shù)據(jù),而都在等待對方釋放鎖才能完成事務(wù)操作,這種情況下就會發(fā)生死鎖。
下圖列出產(chǎn)生鎖定模式的SQL語句:
四、事務(wù)組成:
一條或者多條DML,[一條DDL]和一條DCL。
五、事務(wù)的分類:
1、顯式事務(wù):
- 顯式的調(diào)用DCL。
- 只有用到COMMIT以后才會真正寫入數(shù)據(jù)庫,也持久化了。
2、隱式事務(wù):
- 如果人工要使用隱式事務(wù),SET AUTOCOMMIT ON (只針對一個連接)
- 以下情況為自動提交:
1)正常執(zhí)行完成的DDL語句:create、alter、drop
2)正常執(zhí)行完場的DCL語句GRANT、REVOKE
3)正常退出的SQLPlus或者SQL Developer等客戶端
六、事務(wù)控制命令
1、提交事務(wù)
在執(zhí)行使用COMMIT
語句可以提交事務(wù),當(dāng)執(zhí)行了COMMIT語句后,會確認(rèn)事務(wù)的變化,結(jié)束事務(wù),刪除保存點(diǎn),釋放鎖。當(dāng)使用COMMIT語句結(jié)束事務(wù)之后,其他會話將可以查看到事務(wù)變化后的新數(shù)據(jù)。
2、回滾事務(wù)
保存點(diǎn)(savepoint):是事務(wù)中的一點(diǎn),用于取消部分事務(wù),當(dāng)結(jié)束事務(wù)時,會自動的刪除該事務(wù)所定義的所有保存點(diǎn)。當(dāng)執(zhí)行ROLLBACK時,通過指定保存點(diǎn)可以回退到指定的點(diǎn)。
設(shè)置保存點(diǎn):
Savepoint a;
刪除保存點(diǎn):
Release Savepoint a;
回滾部分事務(wù):
Rollback To a;
回滾全部事務(wù):
Rollback;
七、示例
銀行轉(zhuǎn)帳的例子是最經(jīng)典的事務(wù)示例:
-- 從賬戶一向賬戶二轉(zhuǎn)賬 DECLARE v_money NUMBER(8, 2); -- 轉(zhuǎn)賬金額 v_balance account.balance%TYPE; -- 賬戶余額 BEGIN v_money := &轉(zhuǎn)賬金額; -- 輸入轉(zhuǎn)賬金額 -- 從賬戶一減錢 UPDATE account SET balance = balance - v_money WHERE id = &轉(zhuǎn)出賬戶 RETURNING balance INTO v_balance; IF SQL%notfound THEN raise_application_error(-20001, '沒有該賬戶:' || &轉(zhuǎn)出賬戶); END IF; IF v_balance < 0 THEN raise_application_error(-20002, '賬戶余額不足'); END IF; -- 向賬戶二加錢 UPDATE account SET balance = balance + v_money WHERE id = &轉(zhuǎn)入賬戶; IF SQL%notfound THEN raise_application_error(-20001, '沒有該賬戶:' || &轉(zhuǎn)入賬戶); END IF; -- 如果沒有異常,則提交事務(wù) COMMIT; dbms_output.put_line('轉(zhuǎn)賬成功'); EXCEPTION WHEN OTHERS THEN ROLLBACK; -- 出現(xiàn)異常則回滾事務(wù) dbms_output.put_line('轉(zhuǎn)賬失?。?); dbms_output.put_line(sqlerrm); END;
到此這篇關(guān)于Oracle事務(wù)(transaction)的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持本站。
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。