新聞中心
oracle中數(shù)據(jù)是怎樣前滾和回滾的
保持數(shù)據(jù)一致性和完整性,是每一款成功商業(yè)數(shù)據(jù)庫軟件都必須要做到的基本要求。從故障中恢復,保證ACID原則,保證事務完整性,一直是Oracle數(shù)據(jù)庫核心功能組成部分。本篇主要介紹Oracle實例意外終止(斷電或者強制關(guān)閉)之后,重新啟動時發(fā)生的恢復過程,也可以稱作“前滾和回滾”。
龍口網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、自適應網(wǎng)站建設等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)2013年開創(chuàng)至今到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選成都創(chuàng)新互聯(lián)。
基礎(chǔ)知識說明
為了更明確的說明問題,筆者首先介紹一下本文涉及到的一些重要知識。
數(shù)據(jù)庫實例失敗
我們經(jīng)常說的數(shù)據(jù)庫服務器failure是有多層含義的。Oracle數(shù)據(jù)庫是一個由多進程組件共同構(gòu)成的結(jié)構(gòu)體系。最重要的部分包括監(jiān)聽器、Oracle數(shù)據(jù)庫實例兩個部分,當然還包括各類文件,更廣義的還有硬件和操作系統(tǒng)OS。不同部分的Failure現(xiàn)象和處理方法都有所不同。本文所闡述的過程是Oracle實例失敗后的自動恢復過程。
在實例失敗的時候,往往是突然性的終止。此時Oracle數(shù)據(jù)庫可能在進行一系列完成或者未完成的事務。實例失敗恢復,就是要將這些狀態(tài)進行還原,恢復到數(shù)據(jù)完整性的狀態(tài)。
寫日志(RedoLog)在先機制
Oracle數(shù)據(jù)庫是采用“日志在先”機制的。當我們對數(shù)據(jù)庫數(shù)據(jù)進行修改時,并不是立即將修改寫入到文件中,而是寫入到共享內(nèi)存SGA空間中的BufferCache里。同時,將修改的日志不斷的寫入到SGA中另一塊Log Buffer緩存中。有一個后臺進程LGWR不斷的將LogBuffer緩存中的日志內(nèi)容寫入到online redo log文件中。
寫入LogBuffer緩存和LGWR寫入文件的過程是異步進行的。那么LGWR會在哪些情況下將日志緩沖區(qū)(全部內(nèi)容)轉(zhuǎn)儲到日志文件呢?如下:--參考OCA認證考試指南(1Z0-052,P40)ü 用戶進行直接的commit操作;
ü RedoBuffer數(shù)據(jù)超過1/3;
ü DBWn啟動,將BufferCache中的臟數(shù)據(jù)寫入到文件中;ü 距離上次LGWR寫入操作超過三秒(三秒超時,DBWn每三秒鐘會對一些緩沖區(qū)清理一次,這個時候,剛好符合觸發(fā)LGWR的第三點);而數(shù)據(jù)文件寫入進程DBWn工作的觸發(fā)點(此處注意:DBWn會將高速緩沖區(qū)的臟緩沖區(qū),即臟數(shù)據(jù)塊寫入數(shù)據(jù)文件,而不是緩沖區(qū)里頭的全部內(nèi)容---參考OCA認證考試指南(1Z0-052,P38))。
因為考慮到磁盤I/O會降低性能,DBWn采用的是極懶算法執(zhí)行寫入。如果對于經(jīng)常變臟的緩沖區(qū),即這邊緩沖區(qū)處于十分忙碌的狀態(tài),那么DBWn不會將緩沖區(qū)寫入磁盤的。反而一段時間來,任何會話都未曾關(guān)注的一些緩沖區(qū),DBWn會將其寫入到磁盤。因此DBWn寫臟緩沖區(qū)比較平緩和低頻率。但如果出現(xiàn)檢查點的情況例外:DBWn會將所有臟緩沖區(qū)全部寫入磁盤。---參考OCA認證考試指南(1Z0-052,P38中,P39)。
ü 當BufferCache中沒有任何可用緩沖區(qū);ü 臟緩沖區(qū)過多;
ü 遇到三秒超時(DBWn每三秒鐘會對一些緩沖區(qū)清理一次)ü 遇到檢查點
綜合DBWn和LGWR工作的特點,我們可以得到日志文件的幾個特點:
首先,日志文件的寫入是很頻繁的。LGWR會不斷將日志信息從LogBuffer中寫入Online Redo Log;其次,在日志文件上,可以有三個類型的事務事件。
1、事務結(jié)束,已經(jīng)被commit,之后打過checkpoint檢查點。這種事務記錄在LogFile上,但是變化信息已經(jīng)被DBWn寫入進數(shù)據(jù)文件;2、事務結(jié)束,已經(jīng)被commit,之后沒有打入checkpint檢查點。這種情況下,LogFile已經(jīng)寫入了日志項目,數(shù)據(jù)文件可能包括臟數(shù)據(jù),也可能沒有寫入臟數(shù)據(jù);3、事務未結(jié)束,沒有commit。這種時候,數(shù)據(jù)塊DirtyBlock上面是有事務槽信息,表示未結(jié)束事務,是不會將數(shù)據(jù)寫入到數(shù)據(jù)文件中。但是,日志LogBuffer可能將部分未提交的DML操作項目寫入到Log File中;檢查點Checkpoint
檢查點Checkpoint是數(shù)據(jù)庫一致性檢查的一個標記。簡單的說,就是在這個點上,Oracle保證各個文件(數(shù)據(jù)、控制、日志等)是一致的。檢查點的作用就是在進行實例恢復的時候,告訴SMON進程,這個點之前的內(nèi)容不需要進行恢復。
前滾和回滾介紹
“前滾和回滾”是Oracle數(shù)據(jù)庫實例發(fā)生意外崩潰,重新啟動的時候,由SMON進行的自動恢復過程。下面通過模擬實例和講解介紹這個過程。
失敗前場景說明
日志中記錄過程如下:
1、事務A進行之后,結(jié)束commit。之后系統(tǒng)進行了一次checkpointA;2、Checkpoint之后,進行事務B,結(jié)束commit;3、進行事務C,C事務量較大,其中進行了一定量的RedoLog文件寫入。之后系統(tǒng)斷電;--按照LGWR的工作機制,C事務量比較大,所以應用程序?qū)⒃趲追种幻雰?nèi)的時間里生成足以填充1/3秒的重做內(nèi)容,因此這會觸發(fā)LGWR將日志緩沖區(qū)的內(nèi)容轉(zhuǎn)儲到日志文件,但始終得不到針對C事務的提交記錄,這是需要回滾的。
4、還有種可能,事務B和D,事務D所用的緩沖區(qū)處于高速緩沖區(qū)不活躍的位置,而且事務B已提交,但其所用的緩沖區(qū)處于高速緩沖區(qū)活躍的位置。因此DBWn會將D事務緩沖區(qū)數(shù)據(jù)寫入數(shù)據(jù)文件,而沒將B事務的數(shù)據(jù)寫入。此種情況需要回滾D事務,保留B事務。---參考OCP認證考試指南全冊(P358下半部分內(nèi)容).
1、系統(tǒng)啟動過程,進入實例恢復階段
當實例意外中斷的時候,各類型文件,包括控制文件、數(shù)據(jù)文件和日志文件上,會存在不一致的問題。這種不一致主要體現(xiàn)在SCN值的差異上。
實例在啟動的時候,經(jīng)過三階段(nomount、mount和open)。在open之前,會進行這種不一致現(xiàn)象的檢查,如果出現(xiàn)不一致,要啟動SMON進程的恢復流程。
SMON是Oracle實例的一個后臺進程,主要負責進行系統(tǒng)監(jiān)控恢復。進行恢復的依據(jù)主要是RedoLog記錄。
2、前滾進程
SMON首先找到最后SCN記錄的Redo LogFile。尋找最后一個打入的Checkpoint。
順序找到CheckPointA之后,表示A之前的所有事務都是完全寫入到數(shù)據(jù)文件中,不存在不一致性問題?;謴瓦^程從CheckpointA開始,Oracle開始依據(jù)重做日志Redo Log的系列條目,進行推進。
首先遇到了事務B信息,由于事務B已經(jīng)commit,所以事務B所有相關(guān)的Redo Log條目已經(jīng)全都寫入到Redo LogFile中。所以,按照日志繼續(xù)條目推進,完全可以重演replay,并且應用apply事務B的全部過程。
這樣,事務B全部實現(xiàn),最終將通過DBWn完全寫入到數(shù)據(jù)文件中。所以,實例失敗之前提交commit的事務B,完全恢復。
進入事務C的范疇,由于一部分事務C的RedoLog條目已經(jīng)進入Redo LogFile中(根據(jù)LGWR和DBWn的工作機制,事務C有可能將部分數(shù)據(jù)塊寫入日志文件和數(shù)據(jù)文件,但這時候C事務始終沒提交,這是比較嚴重的訛誤,所以需要回滾),所以在進行前滾的時候,一定會replay到這部分的內(nèi)容。不過,這部分內(nèi)容中不可能出現(xiàn)commit的標記。所以,前滾的結(jié)果一定是遇到實例突然中斷的那個時點。此時replay的結(jié)果是,事務C沒有提交。這樣結(jié)束了前滾過程,進入回滾階段。
3、回滾過程(與普通的回滾一樣(當事務執(zhí)行失敗后自動回滾或者命令:ROLLBACK.)---參考OCP認證考試指南全冊)對事務C(針對DML的update,當然其他同理),要進行回滾過程,釋放所有相關(guān)資源。在前滾中,利用日志填充了的撤銷塊和表數(shù)據(jù)塊的值,然后在回滾的時候,會將撤銷塊的值復制回表數(shù)據(jù)塊中(因為此事務沒提交記錄),以此來進行SGA中BufferCache數(shù)據(jù)塊恢復。
4、說說恢復過程的損耗
很多時候,由于我們事務規(guī)模較大,當出現(xiàn)實例崩潰的時候,重啟所需要的時間很多。有一種經(jīng)驗說法是,事務有多長,前滾和回滾所消耗的時間有多長×2。而且,如果不能完成SMON恢復過程,數(shù)據(jù)庫是不能算作正常的Open的。
SMON的恢復過程是Oracle強制進行的一個過程,即使恢復中發(fā)生斷電或者其他中斷失敗事件。Oracle在下一次啟動的時候,還是會繼續(xù)這個過程,只有耐心等待。
通過檢查一些內(nèi)部視圖(X$視圖),可以觀察到恢復進程和速度,但是絲毫不能影響到最終恢復的過程。
這個過程雖然可以保證數(shù)據(jù)一致性,但是也帶來了系統(tǒng)不能啟動,影響生產(chǎn)環(huán)境的問題。我們可以通過兩個方式進行緩解:
首先,我們在設計開發(fā)系統(tǒng)時,要保證事務規(guī)模的可控性,不要讓事務規(guī)模在技術(shù)層面上過大。避免一旦發(fā)生崩潰,大規(guī)模強制回滾的發(fā)生;其次,一旦出現(xiàn)了這個強制回滾,要注意對生產(chǎn)環(huán)境的影響。可以采用備庫standby進行頂替,讓主庫安靜的慢慢恢復;
oracle中怎么實現(xiàn)數(shù)據(jù)反轉(zhuǎn)
思路:建立一個數(shù)組,用動態(tài)語句實現(xiàn)循環(huán)寫入數(shù)組中,然后再拼成一個變量
更新變量到字段上!
Oracle數(shù)據(jù)庫查詢中返回指定的行數(shù)例如31到40,主鍵ID,但不連續(xù),請問這樣的語句如何寫?
oracle分頁:
select?*?from?(
select?t.*,rownum?from?(
select?*?from?table1?where?condition?order?by?column)?t?)
where?rownum(pangeNow-1)*5?and?rownum=(pageNow)*5
關(guān)于如何從Oracle數(shù)據(jù)庫中寫入和讀取數(shù)據(jù)的一般方法
//定義驅(qū)動名
String url =
"jdbc:oracle:thin:@**.**.**.**:1521:";//定義數(shù)據(jù)庫的鏈接語句,**表示你要鏈接的數(shù)據(jù)庫的ip地址。當然如果你的本機上有oracle也可以寫成127.0.0.1或者localhost,""表示你的數(shù)據(jù)庫名稱。Stringusername ="scott";
//你登陸數(shù)據(jù)庫的用戶名
String password ="*******";
//你登陸數(shù)據(jù)庫的密碼Stringsql= "insert into users(username,password)
values(?,?)";
//插入數(shù)據(jù)的命令語句try{
Class.forName(driver);Connectionconn = DriverManager. getConnection_r(url,
username,password);
PreparedStatement
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,
"god");
//當然為了方便我這是隨便插入的數(shù)據(jù)
pstmt.setString(2,
"god");//同上
pstmt.executeUpdate();
pstmt.close();
conn.close();
//完成后關(guān)閉鏈接
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLExceptione) {
e.printStackTrace();}}}程序運行完成后你就會在你的數(shù)據(jù)庫里看到多了一條記錄username:god
password:god,另外我們覺得這篇博文的讀者應該是那些對oracle數(shù)據(jù)庫有一定的了解的程序開發(fā)愛好者源碼天空
,如果你還不了解oracle,那你就需要對數(shù)據(jù)庫有一定的了解這后再來看這篇博文。
對于一個熱衷于程序設計的人來說,我們認為最主要的是你的程序一定要有一定的標準,我們認為這個例子是鏈接數(shù)據(jù)庫最標準的方法。當然仁者見仁嘛
如何在oracle存儲過程中返回數(shù)據(jù)集
返回記錄集:
CREATE OR REPLACE PACKAGE pkg_test
AS
TYPE myrctype IS REF CURSOR;
PROCEDURE get (p_id NUMBER, p_rc OUT myrctype);
END pkg_test;
/
名稱欄目:oracle如何返寫數(shù)據(jù) oracle返回一條數(shù)據(jù)
文章位置:http://fisionsoft.com.cn/article/hghish.html