成為MySQL DBA後,再看ORACLE資料庫(十、事務與隔離級別)

海布里_MySQL發表於2024-06-16

一、事務控制語句

事務控制方式在ORACLE和MySQL中有著明顯的不同,在ORACLE資料庫中,當第一條可執行的SQL語句開始執行時,就隱性地開始了一個事務,然後繼續執行隨後的SQL語句,直到出現以下情況:1.commit,如果事務遇到commit語句,此前的所有更改將在資料庫中永久生效;2. rollback,如果事務遇到rollback(回滾)語句,則此前的所有更改取消;3.如果使用者發出一條ddl語句,則ORACLE在執行和提交該ddl語句的結果之前,首先提交作為事務一部分的當前所有dml語句,這被稱為隱式提交;4.如果程式結束沒有出現錯誤,則所有更改由資料庫隱式提交;5.如果程式崩潰或中止,它此前所做的所有更改被資料庫隱式回滾。

因此,ORACLE中的事務是隱式自動開始的,但對於事務的結束處理,則需要使用者進行指定的操作。當然ORACLE也可以透過set transaction顯示開啟事務,但實際中很少這麼做。ORACLE的事務控制語句主要有以下幾個:1.commit:當此語句跟在一組dml語句後面時,更改將成為永久的更改;2.rollback;當此語句跟在一個或多個dml語句之後,前面的語句所做的更改被撤銷,如果沒有保留點,則從事務開始起的所有語句都將被回滾;3.savepoint:此語句提供事務的靈活性,幫助設定事務的中間點以便能夠回滾(撤銷)事務;set transaction:指示一個事務的狀態,比如set transaction read only設定只讀事務。

MySQL事務提交方式為預設提交,即執行每一條增刪改DML語句後會預設自動提交,對行鎖的獲取和釋放均很快操作結束,最大程度降低了讀寫事務的衝突,如果需要人為的開啟事務則以begin開始,以commit或rollback結束。需要注意的是,在ORACLE中,有的應用程式使用了ODBC或JDBC,那麼有時候這種介面會帶一個自動提交,即在每個update語句後面悄悄地加一個commit,如果在開發過程中忽略了這個特性將會導致不好的事務習慣。

二、隔離級別

ORACLE支援三種隔離級別:read committed、serializable、read only,預設的隔離級別是read committed,並且在實際使用中也很少用到其他兩種隔離級別。

MySQL的innodb引擎支援ANSI定義的4種隔離級別:read uncommitted、read committed、repeatable read、serializable。MySQL預設的隔離級別是repeatable read,但在實際生產中通常設定為read committed,read committed隔離級別下在一個事務中可以讀到其他事務已提交的資料,雖然這種隔離級別在原則上違背了事務ACID中的一致性,但是在雖然這種隔離級別在原則上違背了事務ACID中的一致性,但是在實際的業務場景下我們可以容忍不可重複讀或幻讀的發生。而repeatable read為了解決幻讀問題引入了next-key lock。因此,為了提升應用的併發性減少鎖等待,read committed是更好的選擇。

三、MVCC

一方面Oracle透過鎖定機制實現資料庫的併發控制;一方面透過多版本(Multi-versioning Model)模型來進行併發資料訪問。透過多版本架構,Oracle實現了讀取和寫入的分離,使得寫入不阻塞讀取;讀取不阻塞修改。這是 Oracle 資料庫區別於其他資料庫的一個重要特徵。Oracle內部使用SCN作為資料庫時鐘,每個資料塊頭部都會記錄一個SCN,當資料更改提交後,SCN同時被修改,這個SCN在查詢時可以用來進行一致性讀判斷。Oracle的多版本模型是透過讀一致性性實現的,Oracle的read committed隔離級別下每個語句都要獲取最新的SCN,假定查詢開始的時間為T1,則在查詢獲取的資料塊中,如果資料塊的提交SCN小於T1,則Oracle接受該資料,如果提交SCN大於T1或者資料被鎖定修改尚未記錄COMMIT SCN,則Oracle需要透過回滾段構造前映象來返回結果,這就是一致性讀的本質含義。在ORACLE中所有的讀操作都是基於快照的讀,寫入需要row lock,如果一個查詢只是讀取資訊,那麼它永遠也不會被阻塞。

相關文章