Decode360's Blog

          業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          數據庫一致性
          ?
          ?
          ??? 一直在將保證數據庫的一致性,但是到底什么是一致性,一般的DBMS如何保證數據庫的一致性的?對這個問題一直都沒有一個很直觀、完整的認識,所以專門研究了一下數據庫的一致性問題,學習的結果如下:
          ?
          ??? 首先摘一段在百度百科上對于“數據庫一致性”的描述:
          ?
          ??? 數據庫一致性(Database Consistency)是指事務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。
          ??? 保證數據庫一致性是指當事務完成時,必須使所有數據都具有一致的狀態。在關系型數據庫中,所有的規則必須應用到事務的修改上,以便維護所有數據的完整性。
          ??? 保證數據庫的一致性是數據庫管理系統的一項功能.比如有兩個表(員工/職位),員工表中有員工代碼、姓名、職位代碼等屬性,職位表中有職位代碼、職位名稱、職位等級等屬性。你在其中員工表中進行了插入操作,你插入了一個新員工的信息,而這個新員工的職位是公司新創建的一個職位。如果沒有一致性的保證,就會出現有這么一個員工,但是不知道他到底擔當什么職責!這個只是它的一個小小方面。
          ??? 讀一致性也是數據庫一致性的一個重要方面,在實際中,我們會遇到這種情況:我們對一個表中的某些數據進行了更新操作,但是還沒有進行提交,這時另外一個用戶讀取表中數據。這個時候就出現了讀一致性的問題:到底是讀什么時候的數據呢?是更新前的還是更新后的?在DBMS中設有臨時表,它用來保存修改前的值,在沒有進行提交前讀取數據,會讀取臨時表中的數據,這樣一來就保證了數據是一致的。(當前用戶看到的是更新后的值)
          ??? 但是還有一種情況:用戶user1對表進行了更新操作,用戶user2在user1還沒有進行提交前讀表中數據,而且是大批量的讀取(打個比方:耗時3分鐘)而在這3分鐘內user1進行了提交操作,那又會產生什么影響呢?這個時候怎么保證讀寫一致性呢?這個時候DBMS就要保證有足夠大的臨時表來存放修改前的數值,以保證user2讀取的數據是修改前的一致數據。然后下次再讀取時候就是更新后的數據了。
          ?
          ?
          ??? 個人認為:從邏輯上來說:當數據庫存在沒有結束的事務時,數據庫就是不一致的。所以要保持數據庫的一致性,就是要確保某一時刻沒有事務在數據庫上執行即可。例如一般說的數據庫一致性備份,就需要在數據庫關閉之后再進行。當然從物理存儲結構考慮一致性的問題會比較復雜一些,因為涉及到很多文件的修改等問題,例如Oracle中的各類SCN的設置。總的來說,可以簡單得認為:所有事務結束后數據庫就是一致的。
          ?
          ??? 所以說:數據庫的一致性的前提是首先要保證事務的一致性。事務的一致性則需要通過并發控制、鎖、隔離性等限制進行保證,具體工作機制可以參見前文,這里就不再研究了。
          ?
          ?
          ?
          Oracle的SCN相關問題
          ?
          ??? 下面摘錄一些Oracle控制一致性的方法,來直觀得了解一下,DBMS是如何來處理一致性的問題的:
          ?
          1、SCN的介紹

          ??? Oracle中的SCN有下面幾種:
          ?
          ??? ①系統檢查點scn(v$database(checkpoint_change#))
          ??????? 當一個檢查點動作完成之后,Oracle就把系統檢查點的SCN存儲到控制文件中
          ??????? select checkpoint_change# from v$database;
          ??? 數據文件檢查點scn (v$datafile(checkpoint_change#))
          ??????? 當一個檢查點動作完成之后,Oracle就把每個數據文件的scn單獨存放在控制文件
          ??????? select name,checkpoint_change# from v$datafile;
          ??? 數據文件終止scn (v$datafile(last_change#))
          ??????? 每個數據文件的終止scn都存儲在控制文件中。在正常的數據庫操作過程中,所有正處于聯機讀寫模式下的數據文件的終止scn都為null
          ??????? select name,last_change# from v$datafile;
          ??? ④數據文件啟動scn (v$datafile_header(checkpoint_change#)
          ??????? Oracle把這個檢查點的scn存儲在每個數據文件的文件頭中,這個值稱為啟動scn,因為它用于在數據庫實例啟動時,檢查是否需要執行數據庫恢復
          ??????? select name,checkpoint_change# from v$datafile_header;
          ?
          2、SCN的工作機制:
          ?
          ??? ①在數據庫打開并運行之后,控制文件中的系統檢查點scn、控制文件中的數據文件檢查點scn和每個數據文件頭中的啟動scn都是相同的
          ?
          ??? ②控制文件中的每個數據文件的終止scn都為null
          ?
          ??? ③NORMAL或IMMEDIATE 關閉數據庫的過程中,系統會執行一個檢查點動作,這時所有數據文件的終止scn 都會設置成數據文件頭中的那個啟動scn的值。
          ?
          ??? ④在數據庫重新啟動的時,Oracle將執行兩次檢查
          ??????? ◆ 看數據文件頭中的ckpt計數器是否與對應控制文件中的ckpt計數器一致。若相等,進行第二次檢查
          ??????? ◆ 比較文件頭中的啟動scn和對應控制文件中的終止scn進行比較,如果終止scn等于啟動scn,則不需要對那個文件進行恢復
          ?
          ??? ⑤數據庫打開之后,存儲在控制文件中的數據文件終止scn的值再次被更改為null,這表示數據文件已經打開并能夠正常使用了
          ?
          ??? 注:當ABORT強制關閉數據庫時不進行檢查點處理,所以終止scn仍然為無窮大。在下次啟動期間,發現啟動scn和終止scn不同,需要進行線程恢復。
          ?
          3、SCN的增加
          ?
          ??? ①SCN(System Change Number)只要數據庫被修改,就會+1,而不是一定要進行checkpoint,例如DML的發生即使沒有提交也會使SCN+1
          ?
          ??? 注:SCN增加并不代表會在數據文件頭中表現出來,而是需要等到checkpoint執行后才寫入(當然可能已經增加了很多)
          ?
          ??? ②如果一個DML導致產生事務,則會產生一個SCN。這個意思是說如果一個事務包含多個dml,則只有第一個初始產生事務的dml產生scn,提交的時候又是一個scn,如果一個事務只有一個dml,拿看起來就是dml產生一個scn,提交或者回滾產生一個scn。
          ?
          ??? ③Oracle 10g內部的SCN會默認不管有沒有動作,每隔3s自動增加一次。其他需要增加的情況則再加。
          ?
          ??? ④只有ckpt進程才會修改文件頭中的checkpoint計數器和SCN,DBWR只會修改數據塊,即ckpt通知dbwr寫數據文件,寫完之后ckpt更新控制文件和數據文件頭。此時若DBWR發現數據塊的log block還沒有被寫入日志文件,則在dbwr寫塊之前通知llgwr把log buffer中的日志寫入log文件。
          ?
          ??? 注:總結一下,日志切換必定出發ckpt,但ckpt不一定會出發llgwr,但是一定會觸發dbwr
          ?
          4、其他的SCN
          ?
          ??? ①日志文件頭中包含了Low scn、Next scn,表示給日志文件包含有從Low scn到Next scn的redo record
          ?
          ??? 注:當系統運行時,日志文件的Next scn同樣為無窮大。而且需要注意:在恢復時不是用日志文件中的Low scn和Next scn來選擇恢復的日志文件,而是通過數據文件頭中的信息。
          ?
          ??? ②數據塊中的SCN
          ??? data block里面的SCN是當block被更改的時候的SCN,而數據文件有那么多 block,自然不同的block有不同的SCN,block中存在block SCN和ITL中的commit SCN。block SCN 又在塊頭和塊位都有,若不一致意味著block損壞。而ITL中的commit SCN則跟consistent gets and delay block cleanout有關。
          ??? ③v$database中的checkpoint_change# 和 dbms_flashback.get_system_change_number 不同。前者是作為數據庫的最后一次checkpoint是的SCN,而后者是系統的最新SCN,所以一般后者都會比前者大,而當剛做完checkpoint時兩者會差不多。
          ?
          ??? ④當begin backup命令發出后,相關數據文件的checkpoint scn被凍結(以及狀態標志被改變),其他一切照舊。例如:日志切換時checkpoint count正常遞增/檢查點照常寫文件,自然文件中的數據塊內的各種scn也照常遞增。
          ?
          ?
          ?
          說明:以上內容均來自IPPUB論壇的一貼討論,來來回回看了好幾遍,又自己實踐了一下才稍微對Oracle的SCN有了一點了解。有時間要學習一下理論知識。
          網址: http://www.itpub.net/viewthread.php?tid=144650&extra=&page=1
          ?
          ?
          ?
          posted on 2009-05-04 22:42 decode360 閱讀(343) 評論(0)  編輯  收藏 所屬分類: 07.Oracle
          主站蜘蛛池模板: 黔西县| 萍乡市| 崇义县| 丁青县| 云林县| 钦州市| 枞阳县| 遵化市| 浏阳市| 阿巴嘎旗| 宁强县| 文登市| 柞水县| 广饶县| 霍城县| 通化市| 惠来县| 裕民县| 三都| 顺义区| 盱眙县| 潜山县| 临汾市| 绥中县| 隆化县| 彰化县| 元氏县| 金昌市| 宜州市| 龙海市| 黑龙江省| 山丹县| 安多县| 青阳县| 辽宁省| 中卫市| 肇东市| 仁怀市| 岱山县| 丽江市| 多伦县|