一 數據庫版本sql
SYS@LEO1>select* from v$version;數據庫
BANNERsession
--------------------------------------------------------------------------------oracle
Oracle Database 11g Enterprise EditionRelease 11.2.0.1.0 - 64bit Production網站
PL/SQLRelease 11.2.0.1.0 - Production.net
CORE 11.2.0.1.0 Production設計
TNS forLinux: Version 11.2.0.1.0 - Production日誌
NLSRTLVersion 11.2.0.1.0 - Production事件
二 事務那些事兒事務
1.什麼是事務:事務是一組操做序列,這些操做要麼都完成,要麼都不完成,它是一個不可分割的操做單元。關係型數據庫最核心的價值體現。說白了爲了完成一件事而作的n個步驟,這n個步驟是有先後順序的,必須按照A->B->C->D的邏輯順序來執行,事務是數據庫維護數據一致性的單位,例如多個會話同時讀取同一數據的問題。
關係型數據庫中,一個事務能夠是一條SQL語句,一組SQL語句或整個程序。
場景:銀行轉帳 結算購物 訂票系統
非關係型數據庫中,一個事務能夠是一個操做,但操做之間沒有關係,相互獨立的。
好比:推薦系統 日誌分析 網站搜索
三 用例子說明事務的四個屬性和自動提交功能
事務的屬性ACID
原子性(Atomicity):一個事務是一個不可分割的總體,事務中的操做要麼都完成,要麼都失敗。
實例
SYS@LEO1>conn leo1/leo1
Connected.
LEO1@LEO1>drop table leo1 purge; 清理環境
Table dropped.
LEO1@LEO1>create table leo1 (x number,ynumber); 建立表
Table created.
LEO1@LEO1>insert into leo1 values(1,1); 執行DML操做
1 row created.
LEO1@LEO1>update leo1 set x=2 where x=1;
1 row updated.
LEO1@LEO1>delete from leo1 where y=1;
1 row deleted.
LEO1@LEO1>commit;
Commit complete.
上面咱們執行了三條sql語句,都屬於一個事務,當commit的時候表示事務完成,這三條sql所有生效,若是rollback這三條sql所有失敗,不存在有的完成有的失敗,由於它們是一個不可再分割的總體。
一致性(Consistency):指數據庫的一種狀態的一致性,具體來講不可違反約束,不可違反規則,所謂的一致性就是一種人爲規則,例如定義一個主鍵,插入2條同樣的數據就違反了一致性條件。
實例
LEO1@LEO1>drop table leo2 purge; 清理環境
Table dropped.
LEO1@LEO1>create table leo2 (x number,ynumber,constraint pk_leo2 primary key(x)); x列有主鍵
Table created.
LEO1@LEO1>insert into leo2 values(1,1);
1 row created.
LEO1@LEO1>insert into leo2 values(1,2); 當插入的值同樣時違反了一致性
insert into leo2 values(1,2)
*
ERROR at line 1:
ORA-00001: unique constraint (LEO1.PK_LEO2)violated
隔離性(isolation):未提交的事務其餘會話不可見。
實例
會話一
LEO1@LEO1>select * from leo2; 表裏只有1條記錄
X Y
---------- ------------------- ----------
1 1
LEO1@LEO1>insert into leo2 values(2,2); 新插入一條
1 row created.
LEO1@LEO1>select * from leo2; 此時表裏有2條記錄,但未有提交
X Y
---------- ------------------- ----------
1 1
2 2
會話二
[oracle@leonarding1 flashback_area]$sqlplus leo1/leo1 鏈接新會話
LEO1@LEO1>select * from leo2; 只能看到已提交事務的數據,未提交的事務看不到
X Y
---------- ----------
1 1
持久性(Durability):事務一旦提交就不可更改,永久有效。
實例
LEO1@LEO1>drop table leo3 purge;
Table dropped.
LEO1@LEO1>create table leo3 (x number,ynumber);
Table created.
LEO1@LEO1>insert into leo3 values(1,1);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select * from leo3;
X Y
---------- ----------
1 1
LEO1@LEO1>rollback;
Rollback complete.
LEO1@LEO1>select * from leo3;
X Y
---------- ----------
1 1
事務一旦commit,你再rollback也是無效的,已經插進去了。
事務是以第一個DML語句做爲開始
如下面其中之一做爲結束
(1) commit or rollback
(2) DDL or DCL
(3) 用戶session正常結束 退出sqlplus
(4) 系統正常結束or終止
事務自動提交,咱們能夠設置oracle自動提交事務
實例
LEO1@LEO1>show autocommit; 默認是不啓動自動提交的
autocommit OFF
LEO1@LEO1>set autocommit on; 手工啓動
LEO1@LEO1>show autocommit;
autocommit IMMEDIATE
LEO1@LEO1>insert into leo3 values(2,2); 當插入數據的同時就提交
1 row created.
Commit complete.
LEO1@LEO1>select * from leo3;
X Y
---------- ----------
1 1
2 2
LEO1@LEO1>rollback; 此時回滾已無效
Rollback complete.
LEO1@LEO1>select * from leo3;
X Y
---------- ----------
1 1
2 2
LEO1@LEO1>set autocommit off; 咱們不建議開啓事務自動提交功能
四 在Oracle下演示Nonrepeatable Read 和PhantomRead的例子,給出SQL演示過程。
Non-repeatable Read不可重複讀:在一個事務中,一樣的數據被2次讀取,獲得不一樣的結果集
實例
Leo幫tiger一塊兒買2張飛機表去肯尼亞看大象
LEO1@LEO1>drop table leo6 purge;
Table dropped.
LEO1@LEO1>create table leo6 (namevarchar2(10),ticket_type varchar2(20),price number);
Table created.
LEO1@LEO1>insert into leo6values('leo','plane_ticket',100);
1 row created.
LEO1@LEO1>insert into leo6values('tiger','plane_ticket',100);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select * from leo6;
NAME TICKET_TYPE PRICE
---------- -------------------- ----------
leo plane_ticket 100
tiger plane_ticket 100
飛機票的價格都是100$,2我的一共200$
Leo查詢的價格
LEO1@LEO1>select sum(price) both_pricefrom leo6;
BOTH_PRICE
------------------
200
在過行李安檢的時候,發現tiger行李超重,原來tiger很是有愛心,給大象帶了花生+毛豆,根據規定超重行李是要補交託運費的。
機場又加了100元託運費
LEO1@LEO1>update leo6 set price=200where name='tiger';
1 row updated.
LEO1@LEO1>select * from leo6;
NAME TICKET_TYPE PRICE
---------- -------------------- ----------
leo plane_ticket 100
tiger plane_ticket 200
LEO1@LEO1>commit;
Commit complete.
Leo再次查詢價格時,總價變成300了
LEO1@LEO1>select sum(price) both_pricefrom leo6;
BOTH_PRICE
------------------
300
不可重複讀在數據庫中是可能出現的,因此要注意一下,上面leo和機場是兩個獨立會話
Phantom Read幻讀:在一個事務中,一樣的sql被2次執行,獲得不一樣的結果集。
實例
翻山越嶺 跋山涉水 終於來到了廣闊的非洲大草原真是大象遍地走 春風吹又生,tiger餚有興致的數起了大象
Tiger 查詢的結果
LEO1@LEO1>drop table leo7 purge;
Table dropped.
LEO1@LEO1>create table leo7 (namevarchar2(10),num number);
Table created.
LEO1@LEO1>insert into leo7values('a',1);
1 row created.
LEO1@LEO1>insert into leo7values('b',1);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select count(*) from leo7; 第一天發現了2只
COUNT(*)
-----------------
2
傍晚有一隻小象跑了過來
LEO1@LEO1>insert into leo7values('c',1);
1 row created.
LEO1@LEO1>commit;
Commit complete.
次日tiger又查詢了一遍,此次發現了3只
LEO1@LEO1>select count(*) from leo7;
COUNT(*)
-----------------
3
小結:上述兩個生動的例子展示了Non-repeatableRead不可重複讀和Phantom Read幻讀的過程,你們必定要好好體會裏面的含義,理解這兩種不一樣的數據讀取方式。
五 在Oracle設計一個場景,會致使Non-repeatableRead,而後選擇一種事務隔離等級來避免它的發生,給出SQL演示過程。
場景:tiger在遊玩非洲大草原以後,選擇從海路回家,在走到索馬里海岸的時候,有幸被海盜光顧,請他上岸吃海鮮,此次海盜拿出了坐享其成的敬業精神,贖金10000$,三天以內交換人質,一手交錢,一手交貨。因爲從來海盜的誠信記錄並非很光彩照人,咱們模擬了一下可能的突發事件。
首先海盜提出條件,贖金10000$,還爲此特地作了一個排行榜
LEO1@LEO1>create table leo8 (namevarchar2(20),cost int); 排行榜清單
Table created.
LEO1@LEO1>insert into leo8values('tiger',10000); 插入tiger信息
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select * from leo8 whererownum<=1; 咱們看到tiger排在第一位
NAME COST
---------------------------------------------------------------
tiger 10000
上面的信息是咱們本身查詢的狀況,忽然海盜得知tiger是中國知名的IT專家,國家的財富和人才。本着生意人的精明頭腦,高價值的人固然換取的條件也水漲船高,海盜偷偷修改了贖金數,變成20000$
海盜
LEO1@LEO1>update leo8 set cost=20000where cost=10000;
1 row updated.
LEO1@LEO1>commit;
Commit complete.
當咱們交錢的時候發現tiger升值了,哎呦我去~ 這不打劫嘛!
LEO1@LEO1>select * from leo8 whererownum<=1;
NAME COST
---------------------------------------------------------------
tiger 20000
爲了防止這種事情發生,咱們可使用Oracle的Read-only事務隔離等級和Serializable事務隔離等級來避免這種事情發生,這兩種事務隔離等級很是類似,所以咱們選擇較經常使用的Serializable來給你們演示。
Read-only事務隔離等級:只能看到事務開始時全部提交的改變,自身不容許DML操做。
Serializable事務隔離等級:只能看到事務開始時全部提交的改變和自身的改變。
當海盜告知咱們贖金是10000$的時候,咱們先開出了清單
LEO1@LEO1>drop table leo8 purge;
Table dropped.
LEO1@LEO1>create table leo8 (namevarchar2(20),cost int); tiger清單
Table created.
LEO1@LEO1>insert into leo8values('tiger',10000);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>set transaction isolationlevel serializable; 咱們設置好了隔離等級
Transaction set.
LEO1@LEO1>select * from leo8 whererownum<=1; 沒錯是10000$
NAME COST
---------------------------------------------------------------
tiger 10000
海盜又故伎重演,想把價格提升到20000$,這是另外一個會話
LEO1@LEO1>update leo8 set cost=20000where cost=10000; 已經更新
1 row updated.
LEO1@LEO1>commit;
Commit complete.
到了較贖金的時候,咱們又查詢了一次
LEO1@LEO1>select * from leo8 whererownum<=1;
NAME COST
---------------------------------------------------------------
tiger 10000
good,完美封殺了海盜邪惡企圖,數據沒有變化,但並非說數據沒有被修改,因爲啓動事務隔離策略,其餘事務所作的修改咱們是看不到的。Serializable只對當前事務有效,不對另外事務有效。
小結:Oracle中全部事務隔離等級都是依賴undo實現的。何時使用Serializable隔離等級好呢,當修改操做比較短的事務,事務中存在多條sql須要數據從事務開始時就保持一致,這樣的場景適合。
六 用示例比較Oracle的Read committed 和Serializable 事務隔離等級的區別,給出SQL演示過程。
Read committed讀已提交事務隔離等級:Oracle 默認隔離等級,支持不可重複讀和幻讀。這兩種數據讀寫方式在第四題中已經徹底闡述了,這裏不在重複。
Serializable 事務隔離等級:只能看到事務開始時全部提交的改變和自身的改變,不支持不可重複讀和幻讀,事務開始是什麼樣子,結果就是什麼樣子,其餘用戶影響不了這個事務。
會話A
LEO1@LEO1>create table leo9(x int,yint); 建立表
Table created.
LEO1@LEO1>insert into leo9values(100,100); 插入一行
1 row created.
LEO1@LEO1>commit; 提交
Commit complete.
LEO1@LEO1>set transaction isolationlevel serializable; 啓動Serializable 事務隔離等級
Transaction set.
LEO1@LEO1>select * from leo9;
X Y
---------- ----------------- ----------
100 100
會話B,咱們用另外一個會話無論怎麼修改leo9表,都不會影響會話A事務
LEO1@LEO1>insert into leo9values(200,200);
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>insert into leo9values(300,300);
1 row created.
LEO1@LEO1>commit;
Commit complete.
會話A,仍是一條數據
LEO1@LEO1>select * from leo9;
X Y
---------- ----------------- ----------
100 100
會話A本身修改的內容在事務中是生效的
LEO1@LEO1>insert into leo9values(400,400); 咱們插入一條記錄
1 row created.
LEO1@LEO1>select * from leo9; 在本事務中是能夠看到的
X Y
---------- ----------
400 400
100 100
LEO1@LEO1>commit; 一旦事務結束,Serializable 事務隔離等級就會失效
Commit complete.
會話A,又能夠看到全部的記錄了
LEO1@LEO1>select * from leo9;
X Y
---------- ----------
400 400
100 100
200 200
300 300
兩種事務隔離等級的比較
Read committed V.S Serializable Transactions
支持SQL92標準 支持SQL92標準
讀取物化視圖 維護語句級一致性 維護事務級一致性
事務一致性 支持語句級 支持事務級
行級鎖 支持 支持
讀鎖定寫 不支持 不支持
寫鎖定讀 不支持 不支持
非行級鎖 不支持 不支持
行級鎖 支持 支持
事務鎖等待 支持 支持
小結:Serializable事務隔離等級做用域是一個事務,超出這個事務就無效了。
事務屬性 Phantom Read Non-repeatableRead Read committed Serializable