serializable隔離級別下事務特性的幾個小測試
oracle裡事務的隔離級別主要有以下三類:
Read Committed
Serializable
Read-only
隔離級別可以在會話、事務兩個級別上進行設定:
———會話級別設定
alter session set isolation_level=read committed;
alter session set isolation_level=serializable;
注:read only無法在會話級別進行設定
———事務級別設定
set transaction isolation level read committed;
set transaction isolation level serializable;
set transaction read only;
其中Read Committed是預設的也是最常用的。
後兩個雖然用的不多,但研究一下也挺有意思,Serializable與Read-only的區別僅在於前者支援DML,關於它們的詳細區別可以參考我的另一篇文章<<設定transaction的讀寫屬性與隔離級別>>:http://blog.itpub.net/53956/viewspace-1286315/
下文以Serializable為例,揭示了該隔離級別下事務所具備的一些特質。
先來看看會話級的設定:
////////////////////////////
// alter session set isolation_level=serializable
////////////////////////////
場景1:在設定session 1的隔離級別為serializable後馬上查詢表,然後在session 2裡再執行更新
select * from t1110_1;
ID
----------
22
33
89
---session 1: app01/app01
alter session set isolation_level=serializable;
select * from t1110_1; <---在session 2執行update前先在session 1執行一次select
ID
----------
22
33
89
---session 2: app01/app01
SQL> update t1110_1 set id=189 where id=89;
SQL> commit;
Commit complete.
SQL> select * from t1110_1;
ID
----------
22
33
189
---session 1: app01/app01
SQL> select * from t1110_1; <---session 1看到的結果與第一次查詢結果一致
ID
----------
22
33
89
rollback;
SQL> select * from t1110_1; <---rollback後能看到最新的更新結果(rollback表示新的事務已經開始)
ID
----------
22
33
189
---session 2: app01/app01
SQL> update t1110_1 set id=133 where id=33; <---再次更新
1 row updated.
SQL> commit;
Commit complete.
---session 1: app01/app01
SQL> select * from t1110_1; <---因為session 1自從上一次select後並未執行commit或rollback,所以看到的還是上一次的結果
ID
----------
22
33
189
SQL> commit; <---執行了commit後標誌這接下來的select能夠訪問到最新修改的結果了
Commit complete.
SQL> select * from t1110_1;
ID
----------
22
133
189
場景2:在設定session 1的隔離級別為serializable後不馬上查詢表,而是等到session 2首次更新後再發起查詢
select * from t1110_1;
ID
----------
22
33
89
---session 1: app01/app01
alter session set isolation_level=serializable; <---此處僅設定session屬性,不執行查詢
---session 2: app01/app01
SQL> update t1110_1 set id=189 where id=89;
SQL> commit;
Commit complete.
SQL> select * from t1110_1;
ID
----------
22
33
189
---session 1: app01/app01
SQL> select * from t1110_1; <---session 1能看到最新的結果
ID
----------
22
33
189
---session 2: app01/app01
SQL> update t1110_1 set id=133 where id=33; <---再次更新
1 row updated.
SQL> commit;
Commit complete.
---session 1: app01/app01
SQL> select * from t1110_1; <---因為session 1自從上一次select後並未執行commit或rollback,所以看到的還是與上一次一致的結果
ID
----------
22
33
189
SQL> commit; <---執行了commit後標誌著接下來的select能夠訪問到最新修改的結果了
Commit complete.
SQL> select * from t1110_1;
ID
----------
22
133
189
場景3:多張表情況下的表現
已存在的表:t1110_1、t1110_2
測試過程中將建立的新表:t1110_4
SQL> select * from t1110_1;
ID
----------
1122
133
189
SQL> select * from t1110_2;
ID
----------
999
888
---session 1:app01/app01
SQL> alter session set isolation_level=serializable;
Session altered.
select * from t1110_1;
ID
----------
1122
133
189
---session 2:app01/app01
SQL> select * from t1110_1;
ID
----------
1122
133
189
SQL> select * from t1110_2;
ID
----------
999
888
SQL> update t1110_1 set id=11122 where id=1122;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from t1110_1;
ID
----------
11122
133
189
---session 1
SQL> select * from t1110_1; <---與首次查詢結果一致
ID
----------
1122
133
189
---session 2
SQL> update t1110_2 set id=9999 where id=999;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from t1110_2;
ID
----------
9999
888
---session 1
SQL> select * from t1110_2; <---查到修改前的結果
ID
----------
999
888
---session 2
SQL> create table t1110_4 (id number); <---建立新表並插入記錄
Table created.
SQL> insert into t1110_4 values(9900);
1 row created.
SQL> commit;
Commit complete.
select * from t1110_4;
ID
----------
9900
---session 1
SQL> select * from t1110_4; <----雖然t1110_4是在session 1設定serializable隔離級別之後建立的,還是能看到表結構,但看不到資料
no rows selected
接著看下事務級的設定
////////////////////////////
// set transaction isolation level serializable
////////////////////////////
SQL> select * from t1110_1;
ID
----------
22
33
89
---session 1:app01/app01
set transaction isolation level serializable;
SQL> select * from t1110_1;
ID
----------
22
33
89
---session 2:app01/app01
SQL> update t1110_1 set id=122 where id=22;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from t1110_1;
ID
----------
122
33
89
---session 1:app01/app01
SQL> select * from t1110_1; <---與首次執行的結果相同
ID
----------
22
33
89
rollback;
SQL> select * from t1110_1; <---rollback後開始新的session
ID
----------
122
33
89
---session 2:app01/app01 進行第二次更新操作
SQL> update t1110_1 set id=133 where id=33;
SQL> commit;
Commit complete.
SQL> select * from t1110_1;
ID
----------
122
133
89
---session 1:app01/app01
SQL> select * from t1110_1; <--- 能看到session 2第二次更新後的結果
ID
----------
122
133
89
set transaction isolation level serializable; <---再次設定成serializable隔離級別
---session 2:app01/app01 進行三次更新操作
SQL> update t1110_1 set id=189 where id=89;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from t1110_1;
ID
----------
122
133
189
---session 1:app01/app01
SQL> select * from t1110_1; <---看到的還是session 2第二次更新後的結果
ID
----------
122
133
89
SQL> rollback;
Rollback complete.
SQL> select * from t1110_1; <---rollback後能看到最新的更新結果
ID
----------
122
133
189
總結:
(1) 會話級設定serializable隔離級別
會話級別上如果將隔離級別設定成了serializable,那麼在這個會話中對錶發起的第一次查詢能查到最近一次commit後的結果,後續發起的查詢查到的結果均與第一次查詢的結果保持一致,其原理應該是記錄了首次查詢期間的SCN,後面如果不commit或者rollback,那麼將一直以這個SCN作為查詢的高水位只返回小於等於此SCN時刻發生的已提交的修改,以上結論只適用於DML操作,對於在SCN時刻之後發生的DDL操作仍能被查到。
當執行commit或者rollback後,意味著新事務的開始,會以當時的SCN作為新的查詢高水位去獲取最新的修改結果。由於serializable的隔離級別設定在session級別,所以只要還在session理,每開始一個新事務就會自動繼承serializable的隔離屬性,不必為每個事務顯式的設定serializable隔離級別
(2) 事務級設定serializable隔離級別
Transaction級別上如果將隔離級別設定成了serializable,那麼當執行了rollback或者commit終止了Transaction後,若要再次進入serializable的隔離級別就必須重新執行set transaction isolation level serializable進行設定。其它特性同會話級設定,不再贅述
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/53956/viewspace-2128280/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 事務、特性、隔離級別
- 事務ACID特性與隔離級別
- 事務基礎特性及隔離級別
- 事務的四大特性,以及隔離級別
- 什麼是事務、事務特性、事務隔離級別、spring事務傳播特性?Spring
- MySQL事務的隔離級別MySql
- MySQL的事務隔離級別MySql
- MySQL 事務隔離級別MySql
- PostgreSQL事務隔離級別SQL
- MySQL事務隔離級別MySql
- [Mysql]事務/隔離級別MySql
- MySQL 事務的四大特性以及隔離級別MySql
- 資料庫事務隔離級別的深坑:預設值應修改為SERIALIZABLE資料庫
- 資料庫事務的四大特性以及事務的隔離級別資料庫
- 事務系統的隔離級別
- 理解mysql的事務隔離級別MySql
- SQL Server事務的隔離級別SQLServer
- 理解MySQL事務隔離級別MySql
- mysql修改事務隔離級別MySql
- Oracle-事務隔離級別Oracle
- JDBC 事務(一) 隔離級別JDBC
- 四個案例看懂 MySQL 事務隔離級別MySql
- SqlServer事務詳解(事務隔離性和隔離級別詳解)SQLServer
- 資料庫事務的隔離級別及四大特性資料庫
- 資料庫事務的四大特性和隔離級別資料庫
- 資料庫事務與事務的隔離級別資料庫
- MySQL 的四種事務隔離級別MySql
- MySQL 事務的隔離級別初窺MySql
- MySQL的四種事務隔離級別MySql
- 怎麼理解SQL的四個事務隔離級別?SQL
- MySQL事務隔離級別和MVCCMySqlMVC
- mysql如何修改事務隔離級別MySql
- mysql事務隔離級別和鎖MySql
- 啥是 MySQL 事務隔離級別?MySql
- Mysql 四種事務隔離級別MySql
- Mysql鎖與事務隔離級別MySql
- 資料庫事務隔離級別資料庫
- MySQL事務隔離級別詳解MySql