1. 程式人生 > 其它 >ORACLE事物隔離級別和髒讀、幻讀、不可重複讀區別

ORACLE事物隔離級別和髒讀、幻讀、不可重複讀區別

一、事務和隔離級別

  事務的概念;事務是把對資料庫的一系列操作都看做一個整體,要麼全部成功,要麼全部失敗,利用事務我們可以保證資料庫的完整性,事務具有原子性。

  隔離級別:隔離級別定義了事務與事務之間的隔離距離。

  事務的隔離級別如下圖:其中 讀已提交(READ COMMITTED) 是ORACLE的預設事務隔離級別


舉例理解不同的隔離級別:髒讀、不可重複讀、幻想讀

  髒讀(Read Uncommitted)
通俗的講,一個事務在處理過程中讀取了另外一個事務未提交的資料。(你都還沒提交,我就讀到了你剛操作的資料,萬一你回滾了怎麼辦,你說這髒不髒。)
舉例(事務B未提交,事務A卻讀到了事務B未提交的資料)

 不可重複讀(nonrepeated read):同一查詢在同一事務中多次進行,由於其他事務提交所做的修改或刪除,導致每次返回的結果不同,此時發生不可重複讀。

通俗的講,一個事務範圍內,多次查詢某個資料,卻得到不同的結果。
與髒讀的區別:髒讀是讀到未提交的資料,而不可重複讀讀到的卻是已經提交的資料,(但實際上是違反了事務的一致性原則)
舉例(事務B提交後,事務A卻讀到了事務B已提交的資料,導致事務A兩次讀到地資料不一致)

  幻想讀(phantom read):同一查詢在同一事務中多次進行,由於其他事務提交所做的插入操作,每次發生的不同的結果集,此時發生幻讀。

事務A讀取與搜尋條件相匹配的若干行。事務B插入符合A事務查詢條件的新行並提交B事務,然後事務A使用相同的條件再次查詢結果集中可以看到事務B插入的記錄,這條新紀錄就像是幻想。
舉例(id主鍵唯一,事務A搜尋id=10的資料,事務A搜尋不到id=10的資料,然後事務B新增id=10的資料並提交,事務A再次搜尋id=10有記錄)


不可重複讀和幻想讀的區別:相同的是兩者均為讀取到已經提交的資料,不同的是前者強調Delete、Update的資料,後者強調Insert的資料。

二、Oracle的隔離級別
  Oracle的事務隔離級別:
    Oracle提供read committed和serializable,並提供了一個非SQL標準的read-only級別。
    Read commit:
      ①這是oracle預設的隔離級別;
      ②保證了不會出現髒讀,但是允許出現非重複讀和幻讀。
    Serializable:
       ①serializable使事務看起來一個接著一個地順序執行(從效果上可以這樣理解)


     ②只能看見在本事務開始前其他事務提交的更改和本事務中所做的更改.
     ③保證不會出現髒讀、不可重複讀和幻讀。
     ④Serializable隔離級別提供了read-only事務所提供的讀一致性,同時又允許DML(update/insert/delete)操作。

三、設定Oracle的隔離級別
  Oracle設定事務的隔離級別:

    設定一個事務的隔離級別:
     Set transaction isolation level read committed;
     Set transaction isolation level serializable;
     Set transaction read only;
    設定整個會話的隔離級別:
    Alter session set isolation level serializable;
    Alert session set isolation level read committed;

四、oracle事務提交機制

Oracle中的事務
1、起始標誌: 事務中的第一條DML語句,即資料修改(增、刪、改)的語句
2、結束標誌: 提交: 顯式 commit 隱式: 正常退出、DDL、DCL
回滾: 顯式 rollback 隱式: 非正常退出 掉電 宕機

提交資料有三種類型:

顯式提交、隱式提交及自動提交。
1、顯式提交:用COMMIT命令直接完成的提交為顯式提交。其格式為:SQL>COMMIT;
2、隱式提交:用SQL命令間接完成的提交為隱式提交。這些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。(此隱式提交是在自己的session,如果在其他人的session(如使用者a)中正在修改相同的資料,則引起隱式提交的語句(使用者a的k另一個session)則必需等待)
3、自動提交:若把AUTOCOMMIT設定為ON,則在插入、修改、刪除語句執行後,系統將自動進行提交,這就是自動提交。其格式為:SQL>SET AUTOCOMMIT ON;

檢視當前是否是自動提交:show autocommit;

隱式提交:

隱式提交的定義
又名自動提交,即無需顯示執行commit語句,session中的操作被自動提交到資料庫的過程。
隱式提交的方式
1、正常執行完ddl語句。包括create,alter,drop,truncate,rename。
2、正常執行完dcl語句。包括grant,revoke。
3、正常退出isql*plus,沒有明確發出commit或者rollback。
隱式提交的注意事項
1、執行ddl語句時,前面的dml操作也會被提交到資料庫中
因為是在一個session裡,那執行ddl語句的時候前面的dml語句肯定也會“不可倖免”的被提交到庫中。
2、即使ddl語句執行失敗,前面的dml操作也會被提交到資料庫中
這就有點兒讓人奇怪了,ddl都執行失敗了,怎麼還會提交呢?這就需要探究一下隱式提交的本質了(下文有敘述)。
3、在前面1和2的基礎上總結
為了避免隱式提交或者回滾,儘量保證一條或者幾條DML操作完成後有顯示的提交或者回滾,防止後續執行的DCL或者DDL自動提交前期的DML操作。
隱式提交的本質
1、一條ddl語句執行了兩次commit
commit;
ddl statement;
commit;
第一個commit將當前session中未提交的事務隱式提交,以保證ddl語句失敗時的回滾位置。
第二個commit將ddl
2、為什麼需要隱式提交?
為了保證事務的一致性。我們在執行ddl語句的時候,oracle需要在它的系統表中進行元資料的記錄操作(即:除了建表還會進行不少insert操作),如果它不隱式提交就無法保證一致性;從內部執行機制來看ddl語句和dml語句還是有很大區別的,dml會對每個語句的每條記錄都做日誌記錄以便於回滾,而ddl往往沒必要搞這麼複雜,從功能和易用性上看隱式提交都是最好的選擇。