【實驗】Oracle的serializable隔離性級別影響

secooler發表於2009-08-11
1.“事務隔離級別”有四種,每種都和“髒讀”、“不可重複讀”和“幻像讀”三個概念有關,請google自學
1)READ UNCOMMITTED
2)READ COMMITED
3)REPEATABLE READ
4)SERIALIZABLE

2.Oracle提供的“事務隔離級別”有上面的READ COMMITED(預設)和SERIALIZABLE外還有READ ONLY
這個可以透過下面的不正當的設定隔離級別的SQL語句的報錯資訊中得到
sec@ora10g> alter session set isolation_level=***;
alter session set isolation_level=***
                                  *
ERROR at line 1:
ORA-02183: valid options: ISOLATION_LEVEL { SERIALIZABLE | READ COMMITTED }
看到了吧,有效的選項是SERIALIZABLE 或 READ COMMITTED。

3.READ COMMITTED級別是預設的,不深入討論,這裡我們實驗一下在SERIALIZABLE隔離級別下資料庫行為是什麼樣的

4.建立測試表test_serializable,並初始化兩條記錄
sec@ora10g> create table test_serializable (a number);

Table created.

sec@ora10g> insert into test_serializable values (1);

1 row created.

sec@ora10g> insert into test_serializable values (2);

1 row created.

sec@ora10g> commit;

Commit complete.

sec@ora10g> select * from test_serializable;

         A
----------
         1
         2

5.重新進入sec使用者,並設定會話的隔離級別為SERIALIZABLE
sec@ora10g> conn sec/sec
Connected.
sec@ora10g> alter session set isolation_level=serializable;


6.另外開啟一個會話更新記錄並提交,注意這裡已經commit提交了修改
sec@ora10g> select * from test_serializable;

         A
----------
         1
         2

sec@ora10g> update test_serializable set a=666 where a=1;

1 row updated.

sec@ora10g> commit;

Commit complete.

sec@ora10g> select * from test_serializable;

         A
----------
       666
         2

7.重新回到第一個會話中,查詢表test_serializable記錄(在預設的READ COMMITED隔離級別應該能看到資料的變化)
sec@ora10g> select * from test_serializable;

         A
----------
         1
         2

到這裡,可以發現表test_serializable中的記錄沒有任何的變化。

這就是SERIALIZABLE隔離級別的效果:
任何其他會話中的資料變更都不會在SERIALIZABLE隔離級別的會話中產生影響。
其實在執行alter session set isolation_level=serializable;設定隔離性級別後,這個會話中所有的查詢狀態就已經固定了。
這個在Oracle中是依靠undo技術來實現的,Oracle會在設定SERIALIZABLE隔離性級別後得到一個一致性的版本。
實驗到這裡就基本可以說明Oracle已經達到了SERIALIZABLE隔離級別的定義效果:不允許有“髒讀”,不允許有“不可重複讀”,不允許有“幻像讀”。

8.進一步,嘗試在SERIALIZABLE隔離級別的會話中重新更新這條資訊會得到什麼樣的效果呢,請看
sec@ora10g> update test_serializable set a=888 where a=1;
update test_serializable set a=888
       *
ERROR at line 1:
ORA-08177: can't serialize access for this transaction

報錯資訊已經提示的很明顯了
原因:更新行已經在其他的會話中進行了修改,版本不一致

9.有沒有想嘗試更新一條沒有被“動過”的資料呢?看看下面的效果:
sec@ora10g> update test_serializable set a=888 where a=2;

1 row updated.

sec@ora10g> select * from test_serializable;

         A
----------
         1
       888

sec@ora10g> commit;

Commit complete.

sec@ora10g> select * from test_serializable;

         A
----------
       666
       888


有意思的現象出現了,不但沒有被“動過”的資料可以修改,而且在commit之後,第一行的記錄資訊也被重新整理成了最新的資料!想一想,這到底是為什麼呢?

10.小結
請見第7點內容

-- The End --

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/519536/viewspace-611860/,如需轉載,請註明出處,否則將追究法律責任。

相關文章