Oracle檢索資料一致性與事務恢複(轉)

來源:互聯網
上載者:User

標籤:無法   href   檢查點   資料   插入   date   http   desc   特定   

在Oracle資料庫中,undo主要有三大作用:提供一致性讀(Consistent Read)、復原事務(Rollback Transaction)以及執行個體恢複(Instance Recovery)。  
      一致性讀是相對於髒讀(Dirty Read)而言的。假設某個表T中有10000條記錄,擷取所有記錄需要15分鐘時間。目前時間為9點整,某使用者A發出一條查詢語句:select * from T,該語句在9點15分時執行完畢。當使用者A執行該SQL語句到9點10分的時候,另外一個使用者B發出了一條delete命令,將T表中的最後一條記錄刪除並提交了。  
那麼到9點15分時,A使用者將返回多少條記錄?  
如果返回9999條記錄,則說明發生了髒讀;如果仍然返回10000條記錄,則說明發生了一致性讀。很明顯,在9點鐘那個時間點發出查詢語句時,表T中確實有10000條記錄,只不過由於I/O的相對較慢,所以才會花15分鐘完成所有記錄的檢索。對於Oracle資料庫來說,沒有辦法實現髒讀,必須提供一致性讀,並且該一致性讀是在沒有阻塞使用者的DML的前提下實現的。  
那麼undo資料是如何?一致性讀的呢?還是針對上面的例子。使用者A在9點發出查詢語句時,伺服器處理序會將9點那個時間點上的SCN號記錄下來,假設該SCN號為SCN9.00。那麼9點整的時刻的SCN9.00一定大於等於記錄在所有資料區塊頭部的ITL槽中的SCN號(如果有多個ITL槽,則為其中最大的那個SCN號)。  
伺服器處理序在掃描表T的資料區塊時,會把掃描到的資料區塊頭部的ITL槽中的SCN號與SCN9:00之間進行比較,哪個更大。如果資料區塊頭部的SCN號比SCN9.00要小,則說明該資料區塊在9點以後沒有被更新,可以直接讀取其中的資料;否則,如果資料區塊ITL槽的SCN號比SCN9.00要大,則說明該資料區塊在9點以後被更新了,該塊裡的資料已經不是9點那個時間點的資料了,於是要藉助undo塊。  
9點10分,B使用者更新了表T的最後一條記錄並提交(注意,在這裡,提交或者不提交並不是關鍵,只要使用者B更新了表T,使用者A就會去讀undo資料區塊)。假設被更新記錄屬於N號資料區塊。那麼這個時候N號資料區塊頭部的ITL槽的SCN號就被改為SCN9.10。當伺服器處理序掃描到被更新的資料區塊(也就是N號塊)時,發現其ITL槽中的SCN9.10大於發出查詢時的SCN9.00,說明該資料區塊在9點以後被更新了。於是伺服器處理序到N號塊的頭部,找到SCN9.10所在的ITL槽。由於ITL槽中記錄了對應的undo塊的地址,於是根據該地址找到undo塊,將undo塊中的被修改前的資料取出,再結合N號塊裡的資料行,從而構建出9點10分被更新之前的那個時間點的資料區塊內容,這樣的資料區塊叫做CR塊(Consistent Read)。對於delete來說,其undo資訊就是insert,也就是說該構建出來的CR塊中就插入了被刪除的那條記錄。隨後,伺服器處理序掃描該CR塊,從而返回正確的10000條記錄。  
讓我們繼續把問題複雜化。假設在9點10分B使用者刪除了最後一條記錄並提交以後,緊跟著9點11分,C使用者在同一個資料區塊裡(也就是N號塊)插入了2條記錄。這個時候Oracle又是如何?一致性讀的呢(假設表T的initrans為1,也就是只有一個ITL槽)?因為我們已經知道,事務需要使用ITL槽,只要該事務提交或復原,該ITL槽就能夠被重用。換句話說,該ITL槽裡記錄的已經是SCN9.11,而不是SCN9.10了。這時,ITL槽被覆蓋了,Oracle的伺服器處理序又怎能找回最初的資料呢? 

 
其中的秘密就在於,Oracle在記錄undo資料的時候,不僅記錄了改變前的資料,還記錄了改變前的資料所在的資料區塊頭部的ITL資訊。因此,9點10分B使用者刪除記錄時(位於N號塊裡,並假設該N號塊的ITL資訊為[Undo_block0 / SCN8.50]),則Oracle會將改變前的資料(也就是insert)放到undo塊(假設該undo塊地址為Undo_block1)裡,同時在該undo塊裡記錄刪除前ITL槽的資訊(也就是[Undo_block0 / SCN8.50])。刪除記錄以後,該N號塊的ITL資訊變為 [Undo_block1 / SCN9.10];到了9點11分,C使用者又在N號塊裡插入了兩條記錄,則Oracle將插入前的資料(也就是delete兩條記錄)放到undo塊(假設該undo塊的地址為Undo_block2)裡,並將9點11分時的ITL槽的資訊(也就是[Undo_block1 / SCN9.10])也記錄到該undo塊裡。插入兩條記錄以後,該N號塊的ITL槽的資訊改為 [Undo_block2 / SCN9.11]。 
那麼當執行查詢的伺服器處理序掃描到N號塊時,發現SCN9.11大於SCN9.00,於是到ITL槽中指定的Undo_block2處找到該undo塊。發現該undo塊裡記錄的ITL資訊為[Undo_block1 / SCN9.10],其中的SCN9.10仍然大於SCN9.00,於是伺服器處理序繼續根據ITL中記錄的Undo_block1,找到該undo塊。發現該undo塊裡記錄的ITL資訊為[Undo_block0 / SCN8.50],這時ITL裡的SCN8.50小於發出查詢時的SCN9.00,說明這時undo塊包含合適的undo資訊,於是伺服器處理序不再找下去,而是將N號塊、Undo_block2以及Undo_block1的資料結合起來,構建CR塊。將當前N號的資料複製到CR塊裡,然後在CR塊裡先回退9點11分的事務,也就是在CR塊裡刪除兩條記錄,然後再回退9點10分的事務,也就是在CR塊裡插入被刪除的記錄,從而構建出9點鐘時的資料。Oracle就是這樣,以層層嵌套的方式,尋找整個undo塊的鏈表,直到發現ITL槽裡的SCN號小於等於發出查詢時的那個SCN號為止。正常來說,當前undo塊裡記錄的SCN號要比上一個undo塊裡記錄的SCN號要小。 但是在尋找的過程中,可能會發現當前undo塊裡記錄的ITL槽的SCN號比上一個undo塊裡記錄的SCN號還要大。這種情況說明由於事務被提交或復原,導致當前找到的undo塊裡的資料已經被其他事務覆蓋了,於是我們無法再找出小於等於發出查詢時的那個時間點的SCN號,這時Oracle就會拋出一個非常經典的錯誤——ORA-1555,也就是snapshot too old的錯誤。 

Oracle為了保證使用者檢索資料的一致性, 通過UNDO記錄,當使用者檢索資料庫資料時,Oracle總是使使用者只能看到被提交過的資料或特定時間點的資料(select語句時間點),UNDO記錄會被存放到復原段中,假如該資料未提交,使用者檢索資料時,都是從UNDO記錄中取得的.(如:)

 

1. ORACLE檢索資料一致性

先開啟一個SecureCRT.(第一個session)

先建一個表

  1. SQL> create table c(a int);  
  2. Table created.  
  3. SQL> alter table c add b number;  
  4. Table altered.  
  5. SQL> desc c   
  6.  Name                                      Null?    Type  
  7.  ----------------------------------------- -------- --------------------------------------------  
  8.  A                                                  NUMBER(38)  
  9.  B                                                  NUMBER  

表中插入資料並提交

  1. SQL> insert into c values(1,2);  
  2. 1 row created.  
  3. SQL> insert into c values(3,4);  
  4. 1 row created.  
  5. SQL> select * from c;  
  6.          A          B  
  7. ---------- -----------------------------  
  8.          1          2  
  9.          3          4  
  10. SQL> commit;  
  11. Commit complete.  

再開啟一個SecureCRT.(第二個session)

查詢

  1. SQL> select * from c;  
  2.          A          B  
  3. ---------- --------------------------  
  4.          1          2  
  5.          3          4  

第一個session更改表中的資料但不提交

  1. SQL> update c set b=10 where a=1;  
  2. 1 row updated.  

第二個session查詢(修改但沒有提交檢索的是UNDO中的資料)

  1. SQL> select * from c;  
  2.          A          B  
  3. ---------- --------------------------  
  4.          1          2  
  5.          3          4  

第一個session提交

  1. SQL> commit;  
  2. Commit complete.  

第二個會話查詢(可見只有提交後才能檢索到資料區段的資料)

  1. SQL> select * from c;  
  2.          A          B  
  3. ---------- -------------------------  
  4.          1         10  
  5.          3          4  

結論:如果使用者修改資料但沒有提交,其它使用者檢索的都是UNDO段的資料,這樣就保證了資料的一致性

2.復原資料(事務恢複)

1.當使用者updata資料但還沒有提交

  1. SQL> select * from c;  
  2.          A          B  
  3. ---------- -----------------------------  
  4.          1          10  
  5.          3          4  
  6. SQL> update c set b=2 where a=1;  
  7. SQL> select * from c;  
  8.          A          B  
  9. ---------- -----------------------------  
  10.          1          2  
  11.          3          4  

這時使用者突然後悔了,想恢複到原來的狀態

  1. SQL> rollback;  
  2. Rollback complete.  
  3. SQL> commit;  
  4.    
  5. SQL> select * from c;  
  6.          A          B  
  7. ---------- -----------------------  
  8.          1         10  
  9.          3          4  

可見當使用者用命今rollback還能復原到初始狀態.

2.當使用者updata資料且已提交

當使用者updata資料且已提交後,可以根據SCN記錄把資料還源.

先查看未經處理資料

  1. SQL> select * from c;  
  2.          A          B  
  3. ---------- ----------  
  4.          1         10  
  5.          3          4  

找到SCN

  1. SQL> select current_scn from v$database;  
  2. CURRENT_SCN  
  3. -----------  
  4.      693636  

現在刪除表中的資料並提交

  1. SQL> delete from c;  
  2. 2 rows deleted.  
  3. SQL> commit;         
  4. Commit complete.  

查詢(現在表中已沒有資料了)

  1. SQL> select * from c;  
  2. no rows selected  

檢索特定SCN的資料

  1. SQL> select * from c as of scn 693636;  
  2.          A          B  
  3. ---------- ----------  
  4.          1         10  
  5.          3          4  

恢複資料

  1. SQL> insert into c select * from c as of scn 693636;  
  2. 2 rows created.  
  3. SQL> commit;  
  4. Commit complete.  

現在再查詢

  1. SQL> select * from c;  
  2.          A          B  
  3. ---------- ----------------------  
  4.          1         10  
  5.          3          4  

可見可以根據SCN恢複到某一檢查點的資料,如果把SCN轉換成時間,,就可以把資料恢複到某一時間點.

 

Oracle檢索資料一致性與事務恢複(轉)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.