日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Oracle数据库之事务

發(fā)布時(shí)間:2024/4/17 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle数据库之事务 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Oracle數(shù)據(jù)庫之事務(wù)

1. 什么是事務(wù)

在數(shù)據(jù)庫中事務(wù)是工作的邏輯單元,一個(gè)事務(wù)是由一個(gè)或多個(gè)完成一組的相關(guān)行為的SQL語句組成,通過事務(wù)機(jī)制確保這一組SQL語句所作的操作要么都成功執(zhí)行,完成整個(gè)工作單元操作,要么一個(gè)也不執(zhí)行。

如:網(wǎng)上轉(zhuǎn)帳就是典型的要用事務(wù)來處理,用以保證數(shù)據(jù)的一致性。

2. 事務(wù)特性

SQL92標(biāo)準(zhǔn)定義了數(shù)據(jù)庫事務(wù)的四個(gè)特點(diǎn):

  • 原子性(Atomicity):一個(gè)事務(wù)里面所有包含的SQL語句是一個(gè)執(zhí)行整體,不可分割,要么都做,要么都不做。
  • 一致性(Consistency):事務(wù)開始時(shí),數(shù)據(jù)庫中的數(shù)據(jù)是一致的,事務(wù)結(jié)束時(shí),數(shù)據(jù)庫的數(shù)據(jù)也應(yīng)該是一致的。
  • 隔離性(Isolation):是指數(shù)據(jù)庫允許多個(gè)并發(fā)事務(wù)同時(shí)對(duì)其中的數(shù)據(jù)進(jìn)行讀寫和修改的能力,隔離性可以防止事務(wù)的并發(fā)執(zhí)行時(shí),由于他們的操作命令交叉執(zhí)行而導(dǎo)致的數(shù)據(jù)不一致狀態(tài)。
  • 持久性 (Durability) : 是指當(dāng)事務(wù)結(jié)束后,它對(duì)數(shù)據(jù)庫中的影響是永久的,即便系統(tǒng)遇到故障的情況下,數(shù)據(jù)也不會(huì)丟失。

一組SQL語句操作要成為事務(wù),數(shù)據(jù)庫管理系統(tǒng)必須保證這組操作的原子性(Atomicity)、一致性(consistency)、隔離性(Isolation)和持久性(Durability),這就是ACID特性。

3. 數(shù)據(jù)異常

因?yàn)镺racle中支持多個(gè)事務(wù)并發(fā)執(zhí)行,所以會(huì)出現(xiàn)下面的數(shù)據(jù)異常。

3.1 臟讀

當(dāng)一個(gè)事務(wù)修改數(shù)據(jù)時(shí),另一事務(wù)讀取了該數(shù)據(jù),但是第一個(gè)事務(wù)由于某種原因取消對(duì)數(shù)據(jù)修改,使數(shù)據(jù)返回了原狀態(tài),這是第二個(gè)事務(wù)讀取的數(shù)據(jù)與數(shù)據(jù)庫中數(shù)據(jù)不一致,這就叫臟讀。

如:事務(wù)T1修改了一條數(shù)據(jù),但是還未提交,事務(wù)T2恰好讀取到了這條修改后了的數(shù)據(jù),此時(shí)T1將事務(wù)回滾,這個(gè)時(shí)候T2讀取到的數(shù)據(jù)就是臟數(shù)據(jù)。

3.2 不可重復(fù)讀

是指一個(gè)事務(wù)讀取數(shù)據(jù)庫中的數(shù)據(jù)后,另一個(gè)事務(wù)則更新了數(shù)據(jù),當(dāng)?shù)谝粋€(gè)事務(wù)再次讀取其中的數(shù)據(jù)時(shí),就會(huì)發(fā)現(xiàn)數(shù)據(jù)已經(jīng)發(fā)生了改變,這就是不可重復(fù)讀取。不可重復(fù)讀取所導(dǎo)致的結(jié)果就是一個(gè)事務(wù)前后兩次讀取的數(shù)據(jù)不相同。

如:事務(wù)T1讀取一行記錄,緊接著事務(wù)T2修改了T1剛剛讀取的記錄,然后T1再次查詢,發(fā)現(xiàn)與第一次讀取的記錄不同。

3.3 幻讀

如果一個(gè)事務(wù)基于某個(gè)條件讀取數(shù)據(jù)后,另一個(gè)事務(wù)則更新了同一個(gè)表中的數(shù)據(jù),這時(shí)第一個(gè)事務(wù)再次讀取數(shù)據(jù)時(shí),根據(jù)搜索的條件返回了不同的行,這就是幻讀。

如:事務(wù)T1讀取一條指定where條件的語句,返回結(jié)果集。此時(shí)事務(wù)T2插入一行新記錄,恰好滿足T1的where條件。然后T1使用相同的條件再次查詢,結(jié)果集中可以看到T2插入的記錄,這條新紀(jì)錄就是幻讀。

事務(wù)中遇到的這些異常與事務(wù)的隔離性設(shè)置有關(guān),事務(wù)的隔離性設(shè)置越多,異常就出現(xiàn)的越少,但并發(fā)效果就越低,事務(wù)的隔離性設(shè)置越少,異常出現(xiàn)的越多,并發(fā)效果越高。

4. 事務(wù)隔離級(jí)別

針對(duì)讀取數(shù)據(jù)時(shí)可能產(chǎn)生的不一致現(xiàn)象,在SQL92標(biāo)準(zhǔn)中定義了4個(gè)事務(wù)的隔離級(jí)別:

隔離級(jí)別臟讀不可重復(fù)讀幻讀
Read uncommitted(讀未提交)
Read committed(讀已提交)
Repeatable read(可重復(fù)讀)
Serializable(串行讀)

Oracle默認(rèn)的隔離級(jí)別是read committed。

Oracle支持上述四種隔離級(jí)別中的兩種:read committed 和serializable。除此之外,Oralce中還定義Read only和Read write隔離級(jí)別。

Read only:事務(wù)中不能有任何修改數(shù)據(jù)庫中數(shù)據(jù)的操作語句,是Serializable的一個(gè)子集。

Read write:它是默認(rèn)設(shè)置,該選項(xiàng)表示在事務(wù)中可以有訪問語句、修改語句,但不經(jīng)常使用。

設(shè)置隔離級(jí)別

設(shè)置一個(gè)事務(wù)的隔離級(jí)別:

  • SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
  • SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
  • SET TRANSACTION READ ONLY;
  • SET TRANSACTION READ WRITE;

注意:這些語句是互斥的,不能同時(shí)設(shè)置兩個(gè)或兩個(gè)以上的選項(xiàng)。

設(shè)置單個(gè)會(huì)話的隔離級(jí)別:

  • ALTER SESSION SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
  • ALTER SESSION SET TRANSACTION ISOLATION SERIALIZABLE;

5. 事務(wù)控制命令

5.1 提交事務(wù)

在執(zhí)行使用COMMIT語句可以提交事務(wù),當(dāng)執(zhí)行了COMMIT語句后,會(huì)確認(rèn)事務(wù)的變化,結(jié)束事務(wù),刪除保存點(diǎn),釋放鎖。當(dāng)使用COMMIT語句結(jié)束事務(wù)之后,其他會(huì)話將可以查看到事務(wù)變化后的新數(shù)據(jù)。

5.2 回滾事務(wù)

保存點(diǎn)(savepoint):是事務(wù)中的一點(diǎn),用于取消部分事務(wù),當(dāng)結(jié)束事務(wù)時(shí),會(huì)自動(dòng)的刪除該事務(wù)所定義的所有保存點(diǎn)。當(dāng)執(zhí)行ROLLBACK時(shí),通過指定保存點(diǎn)可以回退到指定的點(diǎn)。

設(shè)置保存點(diǎn):

sql> Savepoint a;

刪除保存點(diǎn):

sql> Release Savepoint a;

回滾部分事務(wù):

sql> Rollback To a;

回滾全部事務(wù):

sql> Rollback;

6. 數(shù)據(jù)庫鎖

數(shù)據(jù)庫是一個(gè)多用戶使用的共享資源。當(dāng)多個(gè)用戶并發(fā)地存取數(shù)據(jù)時(shí),在數(shù)據(jù)庫中就會(huì)產(chǎn)生多個(gè)事務(wù)同時(shí)存取同一數(shù)據(jù)的情況。若對(duì)并發(fā)操作不加控制就可能會(huì)讀取和存儲(chǔ)不正確的數(shù)據(jù),破壞數(shù)據(jù)庫的一致性。

在數(shù)據(jù)庫中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)。當(dāng)數(shù)據(jù)對(duì)象被加上排它鎖時(shí),其他的事務(wù)不能對(duì)它讀取和修改;加了共享鎖的數(shù)據(jù)對(duì)象可以被其他事務(wù)讀取,但不能修改。

6.1 鎖分類

根據(jù)保護(hù)對(duì)象的不同,Oracle數(shù)據(jù)庫鎖可分為:

  • DML lock(data locks,數(shù)據(jù)鎖):用于保護(hù)數(shù)據(jù)的完整性。
  • DDL lock(dictionary locks,字典鎖):用于保護(hù)數(shù)據(jù)庫對(duì)象的結(jié)構(gòu)(例如表、視圖、索引的結(jié)構(gòu)定義)。
  • Internal locks 和latches(內(nèi)部鎖與閂):保護(hù)內(nèi)部數(shù)據(jù)庫結(jié)構(gòu)。
  • Distributed locks(分布式鎖):用于OPS(并行服務(wù)器)中。
  • PCM locks(并行高速緩存管理鎖):用于OPS(并行服務(wù)器)中。

在Oracle中最主要的鎖是DML鎖,DML鎖的目的在于保證并發(fā)情況下的數(shù)據(jù)完整性。在Oracle數(shù)據(jù)庫中,DML鎖主要包括TM鎖和TX鎖,其中TM鎖稱為表級(jí)鎖,TX鎖稱為事務(wù)鎖或行級(jí)鎖。

鎖出現(xiàn)在數(shù)據(jù)共享的場(chǎng)合,用來保證數(shù)據(jù)的一致性。當(dāng)多個(gè)會(huì)話同時(shí)修改一個(gè)表時(shí),需要對(duì)數(shù)據(jù)進(jìn)行相應(yīng)的鎖定。

鎖有“共享鎖”、“排它鎖”,“共享排它鎖”等多種類型,而且每種類型又有“行級(jí)鎖” (一次鎖住一條記錄),“頁級(jí)鎖” (一次鎖住一頁,即數(shù)據(jù)庫中存儲(chǔ)記錄的最小可分配單元),“表級(jí)鎖” (鎖住整個(gè)表)。

6.2 共享鎖(S鎖)

可通過lock table in share mode命令添加該S鎖。在該鎖定模式下,不允許任何用戶更新表。但是允許其他用戶發(fā)出select …from for update命令對(duì)表添加RS鎖。

6.3 排他鎖(X鎖)

可通過lock table in exclusive mode命令添加X鎖。在該鎖定模式下,其他用戶不能對(duì)表進(jìn)行任何的DML和DDL操作,該表上只能進(jìn)行查詢。

6.4 行級(jí)共享鎖(RS鎖)

通常是通過select … from for update語句添加的,同時(shí)該方法也是我們用來手工鎖定某些記錄的主要方法。比如,當(dāng)我們?cè)诓樵兡承┯涗浀倪^程中,不希望其他用戶對(duì)查詢的記錄進(jìn)行更新操作,則可以發(fā)出這樣的語句。當(dāng)數(shù)據(jù)使用完畢以后,直接發(fā)出rollback命令將鎖定解除。當(dāng)表上添加了RS鎖定以后,不允許其他事務(wù)對(duì)相同的表添加排他鎖,但是允許其他的事務(wù)通過DML語句或lock命令鎖定相同表里的其他數(shù)據(jù)行。

6.5 行級(jí)排他鎖(RX鎖)

當(dāng)進(jìn)行DML操作時(shí)會(huì)自動(dòng)在被更新的表上添加RX鎖,或者也可以通過執(zhí)行l(wèi)ock命令顯式的在表上添加RX鎖。在該鎖定模式下,允許其他的事務(wù)通過DML語句修改相同表里的其他數(shù)據(jù)行,或通過lock命令對(duì)相同表添加RX鎖定,但是不允許其他事務(wù)對(duì)相同的表添加排他鎖(X鎖)。

6.6 共享行級(jí)排他鎖(SRX鎖)

通過lock table in share row exclusive mode命令添加SRX鎖。該鎖定模式比行級(jí)排他鎖和共享鎖的級(jí)別都要高,這時(shí)不能對(duì)相同的表進(jìn)行DML操作,也不能添加共享鎖。

上述幾種鎖模式中,RS鎖是限制最少的鎖,X鎖是限制最多的鎖。它們的兼容關(guān)系如下:

基本上所有的鎖都可以由Oracle內(nèi)部自動(dòng)創(chuàng)建和釋放,但是其中的DDL和DML鎖是可以通過命令進(jìn)行管理的,命令語法:

LOCK table_name IN [row share][row exclusive][share][share row exclusive][exclusive] MODE [NOWAIT];

下圖列出產(chǎn)生鎖定模式的SQL語句:

當(dāng)程序?qū)λ龅男薷倪M(jìn)行提交(Commit)或回滾(Rollback)后,鎖住的資源便會(huì)得到釋放,從而允許其他用戶進(jìn)行操作。如果兩個(gè)事務(wù),分別鎖定一部分?jǐn)?shù)據(jù),而都在等待對(duì)方釋放鎖才能完成事務(wù)操作,這種情況下就會(huì)發(fā)生死鎖

7. 數(shù)據(jù)庫事務(wù)實(shí)現(xiàn)機(jī)制

幾乎所有的數(shù)據(jù)庫管理系統(tǒng)中,事務(wù)管理的機(jī)制都是通過使用日志文件來實(shí)現(xiàn)的,我們來簡(jiǎn)單介紹一下日志的工作方式。

當(dāng)用戶執(zhí)行一條修改數(shù)據(jù)庫的DML語句時(shí),DBMS自動(dòng)在日志文件中寫一條記錄,顯示被這條語句影響的每一條記錄的兩個(gè)副本。一個(gè)副本顯示變化前的記錄,另一個(gè)副本顯示變化后的記錄。當(dāng)日志寫完之后,DBMS才實(shí)際對(duì)磁盤中的記錄進(jìn)行修改。

如果用戶隨后執(zhí)行COMMIT語句,事務(wù)結(jié)束也被記錄在事務(wù)日志中。如果用戶執(zhí)行ROLLBACK語句,DBMS檢查日志,找出自事務(wù)開始以來被修改的記錄“以前”的樣子,然后使用這些信息恢復(fù)它們以前的狀態(tài),有效地撤銷事務(wù)期間對(duì)數(shù)據(jù)庫所做的修改。

如果系統(tǒng)出錯(cuò),系統(tǒng)操作員通常通過運(yùn)行DBMS提供的特殊恢復(fù)程序來復(fù)原數(shù)據(jù)庫。恢復(fù)程序檢查到事務(wù)日志末尾,查找故障之前沒有被提交的事務(wù)?;謴?fù)程序回滾沒有完全完成的事務(wù),以便僅有被提交的事務(wù)反映到數(shù)據(jù)庫中,而故障中正處理的事務(wù)被回滾。

事務(wù)日志的使用明顯增加了更新數(shù)據(jù)庫的開銷。在實(shí)際中,主流商用DBMS產(chǎn)品使用的日志技術(shù)比上述描述的方案更復(fù)雜,用以減小這種開銷。此外,事務(wù)日志通常被存儲(chǔ)在高速磁盤驅(qū)動(dòng)器中,不同于存儲(chǔ)數(shù)據(jù)庫的磁盤,以減小磁盤訪問競(jìng)爭(zhēng)。某些個(gè)人計(jì)算機(jī)DBMS產(chǎn)品允許關(guān)閉事務(wù)日志性能,以提高DBMS的性能。

8. 示例

銀行轉(zhuǎn)帳的例子是最經(jīng)典的事務(wù)示例:

用戶把錢從一個(gè)銀行賬號(hào)轉(zhuǎn)賬至另一個(gè)銀行賬號(hào),需要將資金從一個(gè)銀行賬號(hào)中取出,然后再存入另一個(gè)銀行賬號(hào)中。理想來說,這兩次操作都應(yīng)該成功。但是,如果有錯(cuò)誤發(fā)生,則兩次操作都應(yīng)該失敗,否則的話,操作之后其中一個(gè)賬號(hào)中的金額將會(huì)是錯(cuò)誤的,整個(gè)操作過程應(yīng)該是原子性的,兩個(gè)操作都是一個(gè)原子事務(wù)操作的一部分。

示例:

-- 從賬戶一向賬戶二轉(zhuǎn)賬 DECLAREv_money NUMBER(8, 2); -- 轉(zhuǎn)賬金額v_balance account.balance%TYPE; -- 賬戶余額 BEGINv_money := &轉(zhuǎn)賬金額; -- 輸入轉(zhuǎn)賬金額-- 從賬戶一減錢 UPDATE account SET balance = balance - v_money WHERE id=&轉(zhuǎn)出賬戶RETURNING balance INTO v_balance;IF SQL%NOTFOUND THENRAISE_APPLICATION_ERROR(-20001, '沒有該賬戶:'||&轉(zhuǎn)出賬戶);END IF;IF v_balance < 0 THENRAISE_APPLICATION_ERROR(-20002, '賬戶余額不足');END IF;-- 向賬戶二加錢UPDATE account SET balance = balance + v_money WHERE id=&轉(zhuǎn)入賬戶;IF SQL%NOTFOUND THENRAISE_APPLICATION_ERROR(-20001, '沒有該賬戶:'||&轉(zhuǎn)入賬戶);END IF;-- 如果沒有異常,則提交事務(wù)COMMIT;DBMS_OUTPUT.PUT_LINE('轉(zhuǎn)賬成功');EXCEPTIONWHEN OTHERS THEN ROLLBACK; -- 出現(xiàn)異常則回滾事務(wù)DBMS_OUTPUT.PUT_LINE('轉(zhuǎn)賬失敗:');DBMS_OUTPUT.PUT_LINE(SQLERRM); END;

?

轉(zhuǎn)載于:https://www.cnblogs.com/zf29506564/p/5772380.html

總結(jié)

以上是生活随笔為你收集整理的Oracle数据库之事务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。