1. 程式人生 > >用一個簡單的SQL語句將一個表或者整個資料庫恢復到以前的某一點

用一個簡單的SQL語句將一個表或者整個資料庫恢復到以前的某一點

  除夕之夜,Acme銀行的資料庫管理員(DBA)John正在和他的朋友們一起狂歡,倒計時迎接新的一年的到來。就在子夜鐘聲敲響、人群歡呼之時,他的尋呼機突然響了。在銀行的資料中心,在年末進行利息累機批處理簿記過程中發生了錯誤,所有的利息計算都不準確。幸好開發團隊找出了錯誤所在,並開發一個應急糾正模組,但這一糾正模組不能恢復已經造成的破壞。部門經理問John是否有什麼方法能往回倒一些時間,將資料庫恢復至該批處理開始之前的狀態,該批處理大約是在晚上11:00開始的。
  
  對於DBA們來說,這不是一件很熟悉的事嗎?John的選擇是什麼呢?
  
  在Oracle資料庫10g之前,John可能會做一個時間點恢復,來將資料庫恢復至所希望的某一時刻的狀態。不幸的是,銀行的定期日常備份大約就是在那個時間開始,這就意味著他將不得不用接近24小時的有價值的歸案日誌來恢復資料庫。
  
  Oracle9i資料庫中提供的另一種選擇是使用回閃查詢特性來重建到晚上11:00為止的該表的各行,並手動生成一組不同的表。這一方法儘管理論上可行,但如果表的數量很大,則會變得不切合實際。
  
  幸運的是,John現在的資料庫是Oracle資料庫10g,所以他擁有更多的選擇。
  
  回閃表
  
  讓我們來看一下上面的情況。出問題的年末批處理可能僅影響少數表。例如,它可能僅用新的賬戶結餘更新了ACCOUNTS表。如果確實是這種情況,則John可以使用回閃表特性,它會將一個表恢復到一個過去的時間點的狀態。
  
  執行回閃表操作不需要特殊的設定。唯一的要求是表必須具有可移動的行--或者是在建立表時設定,或者是在以後利用 ALTER TABLE ACCOUNTS ENABLE ROW MOVEMENT語句設定。FLASHBACK TABLE語句從撤消段中(undo segment)讀取該表的過去映像,並利用Oracle9i中引入的回閃查詢重建錶行。
  
  如果模式所有者之外的非DBA使用者執行回閃表操作,她需要擁有對該表的SELECT、 DELETE、INSERT、ALTER和FLASHBACK許可權,或者擁有等價的ANY TABLE系統許可權。
  
  對於John來說,ACCOUNTS像以下的樣子:
  
  ACCOUNT_NO  NUMBER(12),
  BALANCE   NUMBER(15,2)
  STATUS    CHAR(1)
  STATUS的列值通常為A(active,活動),但是當利息計算應用程式啟動時,所有的賬戶均被凍結,此狀態也被更新為F(frozen,凍結)。當對每一賬戶都計算了利息後,該狀態被更新為I(interest applied,利息已計算)。
  
  下面是John用使用回閃表特性的步驟:
  
  他索要一個大概的時間點,在這一點上資料庫必須被重新檢查,答案是大約晚上11:00。
  
  他定義一個期望返回到的邏輯參考點。下面是他現在查詢該表時所看到的內容:
  
  select status, count(*)
  from ACCOUNTS
  group by status;
  
     STATUS  COUNT(*)
     ------ --------
     I     27088
     F     19999
  
  該輸出顯示到目前為止已經有27 088個賬戶被處理(狀態=I)。 此前的狀態為A,這不是John所希望返回的位置。所希望的邏輯參考點應該是所有賬戶的狀態都為F的時間點。他必須恢復到所有賬戶狀態都為F的狀態,這大約發生於晚上11:00。
  
  他檢查一個狀態=I的當前示例賬戶,以便為未來的校驗測試設定一個基線:
  
  select account_no, balance
  from ACCOUNTS
  where status = I
  and rownum < 2;
   ACCOUNT_NO  BALANCE
  -----------  --------
     21633  3913.49
  
  他發出這一語句將ACCOUNTS表恢復至那個時間:
  
  flashback table ACCOUNTS to timestamp
  to_timestamp (12/31/2003 23:00:00,mm/dd/yyyy hh24:mi:ss);
  
  瞧! 整個表被恢復到那個時間的狀態了。只要撤消段中所儲存的撤消資料允許,John便可以回閃到過去的某個時間點。John也可以不用時間標記(stamp),而是使用系統改變數目(system change number,SCN),如下所示:
  
  flashback table ACCOUNTS
  to SCN 9988653338;
  
  此表已被恢復至晚上11:00的狀態,但這是不是所希望的時間點狀態呢?John再次檢查狀態:
  
  select status, count(*)
  from ACCOUNTS
  group by status;
  
  STATUS  COUNT(*)
  ------  --------
  I       88
  F     46999
  
  仍然有88個記錄的狀態為T。所以,晚上11:00還不夠早,John不得不返回到更早的一個時間點。他將該表回閃到更早的一個時間點上--晚上10:30--然後再次檢查狀態:
  
  flashback table ACCOUNTS to timestamp
  to_timestamp (12/31/2003 22:30:00,mm/dd/yyyy hh24:mi:ss);
  
  select status, count(*)
  from ACCOUNTS
  group by status;
  
  STATUS  COUNT(*)
  ------  --------
  A     47087
  
  John返回到的過去時間太遠了些,所有賬戶的狀態都為A,這是F狀態之前的一個狀態。於是,他不得不向後滾動一段時間,滾動到晚上10:45。
  
  flashback table ACCOUNTS to timestamp
  to_timestamp (12/31/2003 22:45:00,mm/dd/yyyy hh24:mi:ss);
  
  select status, count(*)
  from ACCOUNTS
  group by status;
  
  STATUS  COUNT(*)
  ------  --------
  F     47087
  
  這正是他希望的時間點。他通過選擇他以前查詢過的賬戶來確證這一點。
  
  select balance
  from ACCOUNTS
  where account_no = 21633;
  
  BALANCE
  -------
  3836.75
  
  有效的結餘為$3,913.49;返回到了晚上10:45的狀態。至此操作完成。可以向前和向後應用任意次回閃操作,直到到達所期望的準確時間點的狀態為止。
  
  由於此表永遠不會被刪除,所以所有的從屬物件--如索引、約束條件、觸發器等等--都會保持完好無損。引用此表的所有獨立物件,如過程等,也都保持有效。即使是對分割表的全域性索引也會保留,並保持有效。
  
  除了ACCOUNTS表之外,如果John還希望將TXN表回閃,那麼他可以應用許多由逗號隔開的表名,如下所示:
  
  flashback table BANK.ACCOUNTS, bank.txn to scn 1234567;
  
  通過一個功能強大的SQL語句完成了整個回閃表操作。
  
  讓我們來研究另一種情況。假設Laura意外地刪除了一個關鍵字查詢表--GL_MASTER。意識到這一錯誤後,她問John能否恢復這個表。在 Oracle資料庫的以前一些版本中,這需要進行時間點恢復。但在Oracle資料庫10g中,刪除一個表只是將該表重新命名後放置到稱作回收站的邏輯容器中。
  
  為了恢復此表,John只發出了以下命令:
  
  flashback table gl_master to before drop;
  
  這個表馬上就重新出現了,不需要任何恢復操作。請注意,與前面所描述的回閃操作不同,它不需要通過撤消段重建資料;而只是從回收站中將此表取回。
  
  回閃資料庫

  
  如果說邏輯上的破壞不限於為數不多的幾個表,那麼利用Oracle 10g中的Flashback Database(回閃資料庫)特性執行資料庫時間點恢復可以使恢復更快一些。Flashback Database不需要利用撤消空間(undo space),而是利用硬碟上被稱作快閃恢復區(flash recovery area)的另一區,它與撤消操作無關。Flashback Database允許進行資料庫時間點恢復,而不要求你首先恢復你資料庫的一個備份。
  
  要回閃整個資料庫,John必須進行以下操作為資料庫做準備,從而使其具有回閃能力:
  
  通過設定以下兩個引數來配置一個大小為2GB的回閃區域:
  
  db_recovery_file_dest = /usr/users/oracle/10.1/recovery_area
  db_recovery_file_dest_size = 2G
  
  使用以下引數,以分鐘為單位配置最大回閃時間:
  
  db_flashback_retention_target = 1440
  
  這一數值反映出可以返回的最大時間;實際可能的時間由快閃恢復區域的可用空間大小來決定。所以這三個引數都是動態的,並可以使用ALTER SYSTEM命令進行設定。
  
  使資料庫能夠回閃。為此,它必須處於archivelog模式下。在MOUNT階段,在OPEN之前,John發出如下命令:
  
  alter database flashback on;

  
  在啟動Flashback Database之後,它定期將已發生變化的塊寫入一個特殊型別的稱作回閃日誌的日誌檔案中。這些日誌不是由傳統的Log Writer (LGWR) 過程寫入,而是由一種稱作Recovery Writer (RVWR)的新過程寫入。與常規的重做日誌(redo logs)不同,回閃日誌既不需要由DBA建立,也不需要由他們維護;它們由Oracle Managed Files(OMF)自動在快閃恢復區域所指定的目錄中建立。這些檔案不會歸檔,所以,如果在該目錄發生介質故障後就不可能再進行恢復。
  
  回閃操作
  
  在所描述的Acme銀行的事例中,John認為在他所處的情況下回閃表不太可行。他不得不將整個資料庫回滾到過去的某個時間點。他再一次選擇晚上11:00作為開始點,併發出以下命令:
  
  flashback database to timestamp
  to_timestamp (12/31/2003
  23:00:00,mm/dd/yyyy hh24:mi:ss);
  
  這一操作執行所有的必要任務,如使  

相關推薦

一個簡單SQL語句一個或者整個資料庫恢復以前一點

  除夕之夜,Acme銀行的資料庫管理員(DBA)John正在和他的朋友們一起狂歡,倒計時迎接新的一年的到來。就在子夜鐘聲敲響、人群歡呼之時,他的尋呼機突然響了。在銀行的資料中心,在年末進行利息累機批處理簿記過程中發生了錯誤,所有的利息計算都不準確。幸好開發團隊找出了錯誤所在

SQL 語句 一個中用特殊字元分割的欄位轉換成多行資料

在開始寫之前需要先說下這兩個函式的用法, SubString(str,pos,len): 從pos位置擷取字串STR,len個字元 CHARINDEX ( expression1 ,expression2, [ start_location ] ) :expression

SQL語句一個的數據寫入到另一個

.cn index href 有時 eat int 順序 過程 方式 在日常的數據庫運維過程中,有時候需要將Select查詢出來的數據集寫入到另一個數據表中,其中一種方式是通過存儲過程循環寫入數據,另一種簡便的方式是直接使用Insert Into語句後面跟上Select結果

【存儲過程】SQL語句獲得一個存儲過程返回的

into log 返回 dbo emp ins 過程 arc 存儲過程 定義一個存儲過程如下: create proc [dbo].[test1] @id int as select 1 as id,‘abc‘ as name union all select @id

SQL語句一個的增加自增主鍵或刪除主鍵

剛開始時碰到這個需求時,在網上搜索了一下,發現都說不行,得先刪除那主鍵列再重新增加或者先建立一個臨時表再把資料導過來,其實在MYSQL中是可以直接修改的。 修改ID欄位為自增主鍵: alter table `test` change `id` `id` int (11) U

sql一個中的數據註入另一個

一個表 .com 分享 兩個 image hbm inf left info sql之將一個表中的數據註入另一個表中 需求:現有兩張表t1,t2,現需要將t2的數據通過XZQHBM相同對應放入t1表中   t1:      t2:    思路:left join

sql語句一個中含有id和父親id,統計父親有多少個孩子

將表和他自己連線~ select * from tb_comment a left join tb_comment b on b.c_fatherid=a.cid 得到右側有空的結果,空的地方count(*)會被統計,用count(column)不會被統計~ 1)count(*

SQL語句 使用一個更新另一個的方法

MERGE INTO T T1   USING (SELECT '1001' AS a,2 AS b FROM dual where = b > 0) T2   ON ( T1.a=T2.a)   WHEN MATCHED THEN    UPDATE SET

Sql Server 一個中的資料複製到另個一

目標表存在 將table1中資料全部複製到table2中(table1,table2表結構一致) insert into table1  select * from table2 將table1中name為張三的資料複製到table2中(table1,table2表結構

SQL語句遠端SQL Server資料庫中表資料匯入到本地資料庫相應的

exec sp_addlinkedserver ‘名稱’,”,’SQLOLEDB’,'遠端資料庫的地址’ exec sp_addlinkedsrvlogin ‘名稱’,'false’,'本地使用者名稱稱’,'遠端使用者名稱稱’,'遠端使用者密碼’ 2、倒入表 insert

SQL 語句 對於一個的基本操作

首先建立一個基本的表,在定義列名時注意賦預設值,注意使用者定義完整性這一約束條件 create table base( col1 varchar(50) primary key, --主鍵 預設不為空 colF varchar(50), col2 int defaul

c++連結SQL server ,SQL語句打印中的記錄,增加中的記錄,刪除的欄位

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF", "adoEOF") rename("BOF", "adoBOF") // 唯一的應用程式物件 CWinApp

pandas讀取20W資料excel,每999行生成一個查詢sql語句

前言 工作中遇到一個小問題,Oralce資料庫的查詢是不能大於1000條in查詢的,所以需要對檔案進行切割。資料來源是20w的excel資料,於是想到用pandas對其進行讀取,然後每998行生成一個新的sql檔案。 程式碼實現 # coding = utf-8 """ @

一句sql語句更新兩個並可更新對應的欄位的值

ACCESS 例子: insert into products (ProNumber,CASNumber,Cnname,Price,Enname,Baozhuang,Pinpai) select ProNumber,CASNumber,Cnname,Price,Enname,Baozhuan

記錄一個SQL語句不好的習慣挖的坑

如果表中欄位很多,型別很雜,不要怕麻煩,一定要引數化SQL語句。 拼接SQL語句容易導致SQL注入就不用說了,關鍵是出了錯也不好查出來。 比如我要存一個圖片,存在text型別的欄位中,不管圖片路徑做不做加密,傳進去的圖片路徑多少都會帶有的符號,而拼接字串導致了我沒有辦法處

sql語句一張中的一列插入到另一張

如下兩張表student和course               現在想要將course表的cname列插入到student表中。(有兩種方法) 方法一: 語句如下: alter table stu

sql 語句兩張合併成一張

比如 表1結構為: A     B     C 1     2      3 表2結構為:

資料庫,3個欄位,姓名,薪水,部門,一條sql語句求每個部門薪水最高的人姓名

select t1.姓名 from 表 t1, (select max(薪水) 薪水,部門 from 表 group by 部門) t2 where t1.部門=t2.部門 and t1.薪水 = t2.薪水 create table t1 (   NAME VARCH

一個因為sql語句引起的伺服器掛掉

左連線(LEFT JOIN)例項 現在,我們希望列出所有的人,以及他們的定購 - 如果有的話。 您可以使用下面的 SELECT 語句: SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons LEFT JOIN Orde

一條SQL語句查詢一張得到不同條件的多個結果

一條語句,12個結果,12行,比較方便與1個dataGridView的現實。 我是用在C# Winform上的3層結構的開發上,用這個實現統計12個月每個月的銷售總額。現在就差統計表了,GDI功底比較差,還在研究呵呵。 SELECT A1.date 日期, SUM(A1.s