一、事務和隔離級別
事務的概念;事務是把對數據庫的一系列操作都看做一個整體,要么全部成功,要么全部失敗,利用事務我們可以保證數據庫的完整性,事務具有原子性。
隔離級別:隔離級別定義了事務與事務之間的隔離距離。
事務的隔離級別如下圖:其中 讀已提交(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往往沒必要搞這么復雜,從功能和易用性上看隱式提交都是最好的選擇。