【OCP最新題庫解析(052)–題60】Which three are true about UNDO data?

  • 2019 年 10 月 11 日
  • 筆記

該系列專題為2018年4月OCP-052考題變革後的最新題庫。題庫為小麥苗解答,若解答有不對之處,可留言,也可聯繫小麥苗進行修改。

註:OCP-052最新題庫完整詳細解答版請聯繫小麥苗私聊。解題不易,請大家尊重原創。

題目

Which three are true about UNDO data?

A. It is used to rewind a database by using FLASHBACK DATABASE.

B. It is used to recover dropped tables by using FLASHBACK TABLE … TO BEFORE DROP.

C. It is used to enable ROLLBACK statements to roll back uncommitted updates.

D. It is used to roll back failed transactions.

E. It is used during online backups to guarantee their consistency.

F. It is used to provide read consistency.

A

答案

Answer:CDF

Oracle中閃回技術分類圖如下所示:

Undo主要有以下幾個作用:

(1)事務回滾(Rollback Transaction)

當一個事務修改表中數據的時候,該數據修改前的值(即前鏡像,Before Image)會被存放在Undo段中,當用戶回滾事務(ROLLBACK)時,Oracle將會利用在數據塊ITL槽中記錄的Undo塊地址(Undo Block Address,Uba),然後找到相應的Undo塊,接著利用其中的Undo數據(即前鏡像)來將修改的數據恢復到原來的值,從而實現對事務所作的改變進行回滾。

(2)事務恢復(Transaction Recovery)

實例恢復(Instance Recovery)的第一階段稱為前滾(Rolling Forward)或者快取恢復(Cache Recovery),第二階段稱為回滾(Rolling Back)或者事務恢復。前滾和回滾是Oracle資料庫實例發生意外崩潰,重新啟動的時候,由SMON進行的自動恢復的過程。所謂的前滾,是應用Redo來恢復Buffer Cache的數據,將Buffer Cache恢復到Crash之前狀態,所以此時Buffer Cache中既有崩潰時已經提交但還沒有寫入數據文件的臟塊,還有事務被突然終止而導致的既沒有提交又沒有回滾的事務的臟塊(也就是沒有COMMIT,但是DBWn已經將改變的數據刷新到底層磁碟)。前滾完成之後就可以確保聯機Redo日誌中所有已提交的事務操作的數據寫回到數據文件中。接下來,前滾之後,任何未提交的更改必須被撤消,而回滾是在資料庫做完前滾操作後並打開資料庫的情況下完成的,SMON會利用Undo資訊將未提交的事務全部進行回滾。具體來說,SMON進程在完成前滾後,查看Undo段頭(Undo段的第1個數據塊)記錄的事務表(每個事務在使用Undo塊時,首先要在該Undo塊所在的Undo段頭記錄一個條目,該條目里記錄了該事務相關的資訊,其中包括是否提交等),將其中既沒有提交也沒有回滾,而是在實例崩潰時被異常終止的事務全部回滾。

(3)提供一致性讀(Consistent Read)

Oracle是一個多用戶系統,當一個會話開始讀取數據還未結束讀取之前,可能會有其他會話修改了該會話將要讀取的數據。如果會話讀取到修改後的數據,那麼就會造成數據的不一致,出現了臟讀(Dirty Read)。所以,一致性讀是相對於臟讀而言的。在Oracle中,一致性讀是通過Undo來實現的,一致性讀就是為了保證數據的一致性。在一般情況下,普通查詢都是一致性讀。

舉例來說,假設某個表T中有1W條記錄,獲取所有記錄需要15分鐘時間。當前時間為9點整,某用戶A發出一條查詢語句:「SELECT * FROM T;」,該語句在9點15分時執行完畢。當用戶A執行該SQL語句到9點10分的時候,另外一個用戶B發出了一條DELETE命令,將T表中的最後一條記錄刪除並提交了。那麼到9點15分時,A用戶將返回多少條記錄?如果返回9999條記錄,那麼說明發生了臟讀;如果仍然返回1W條記錄,那麼說明發生了一致性讀。很明顯,在9點鐘那個時間點發出查詢語句時,表T中確實有1W條記錄,只不過由於I/O的相對較慢,所以才會花15分鐘完成所有記錄的檢索。對於Oracle資料庫來說,必須提供一致性讀,並且該一致性讀是在沒有阻塞用戶的DML操作的前提下實現的。

那麼Undo數據是如何實現一致性讀的呢?在Oracle資料庫中的Buffer Cache中的數據塊上都會有最後一次修改數據塊時的SCN。如果一個事務需要修改數據塊中數據,那麼會先在回滾段中保存一份修改前數據和SCN的數據塊,然後再更新Buffer Cache中的數據塊的數據及其SCN,並標識其為「臟」數據。當其它進程讀取數據塊時,會先比較數據塊上的SCN和自己發出SQL語句時刻的SCN,分為以下兩種情況:

① 如果該數據塊頭部的ITL槽上記錄的SCN大於自己查詢時刻的SCN,那麼表示該塊被更新過,此時就要藉助Undo塊了。在該數據塊頭部的ITL槽上記錄了對應的Undo塊的地址(Uba),根據Uba就可以找到對應的Undo塊。如果發現該Undo塊的ITL槽的SCN號也較大,證明該Undo塊也不可用,那麼需要在該塊的ITL槽上繼續尋找上一個Undo塊地址,層層遞歸,最終找到SCN號比發出查詢的SCN號小的Undo塊,將該Undo塊中的被修改前的數據取出,從而構建出發出SQL語句時刻的數據塊內容,這樣的數據塊叫做CR(Consistent Read)塊。但是在查找的過程中,可能會發現當前Undo塊里記錄的ITL槽的SCN號比上一個Undo塊里記錄的SCN號還要大。這種情況說明由於事務被提交或回滾,導致當前找到的Undo塊里的數據已經被其它事務覆蓋了,於是就無法再找出小於等於發出查詢時的那個時間點的SCN號,這時Oracle就會拋出一個非常經典的錯誤–ORA-1555,也就是snapshot too old(快照過舊)的錯誤。對於DELETE來說,其Undo資訊就是INSERT,也就是說該構建出來的CR塊中就插入了被刪除的那條記錄。

② 如果數據塊頭部的ITL槽(事務槽)上記錄的SCN小於等於自己查詢時刻的SCN,那麼分為兩種情況:第一,若被查詢的塊上沒有活動的事務,則表示該塊沒有被更新過,是可用的,可以直接讀取該數據塊上的數據;第二,若被查詢的塊上有活動的事務,則需要找Undo的前鏡像數據。

(4)實現閃回功能

閃回功能中的閃回查詢(Flashback Query)、閃回版本查詢(Flashback Version Query)、閃回事務查詢(Flashback Transaction Query)和閃回表(Flashback TABLE)都是基於Undo表空間中的回滾資訊實現的。