oracle學習筆記 Oracle日誌核心意義_快速提交_寫緩存



oracle學習筆記  Oracle日誌核心意義_快速提交_寫緩存

oracle實例有
dbf、buffercache、logbuffer、redolog


一)oracle中的事務


oracle有一個原則
所有已提交事務oracle保證不會丟失


先退出目前會話
SQL> exit


然後重新登陸
[oracle@redhat4 ~]$  sqlplus / as sysdba
這時的這個會話是乾淨的沒有任何的事務


執行一條命令

SQL> delete from t1 where rownum=1;

1 row deleted.

從t1刪了一行數據


登陸了數據庫以後,然後刪了一行數據
這個時候其實是一個事務開始了


這時再敲了一個命令commit,叫提交
這就是一個事務


可以這麼認爲
一個事務是由一條和多條增刪改數據組成一個事務
就是一條或多條DML語句


關係數據庫的標準語言爲結構化查詢語言(Structured Query Language)
最多可分爲六個類型
數據查詢語言(DQL:Data Query Language) 如:SELECT語句
數據操作語言(DML:Data Manipulation Language) 如:INSERT、UPDATE、DELETE等語句
數據定義語言(DDL:Data Definition Language) 如:CREATE、DROP、ALTER等語句
數據控制語言(DCL:Data Control Language) 如:GRANT、REVOKE、DENY等語句
事務處理語言(TPL:Transaction Processing Language) 如:BEGIN TRANSACTION、COMMIT、ROLLBACK、SAVEPOINT等語句
指針控制語言(CCL:Cursor Control Language) 如:DECLARE CURSOR、FETCH INTO、UPDATE WHERE CURRENT等語句


習慣上有人把DQL併入DML,也有把DCL併入DDL的
很多分類方法沒有指出CCL


事務和oracle的一致性關係非常緊密
很多人就是因爲在事務這個概念上沒有注意
最後導致數據庫的數據被損壞


在實際中事務很簡單
就如剛纔講的原理,講課內容還有實際操作都很簡單
所以很多人在事務上沒有引起重視
實際工作中經常容易犯的一些和事務相關的錯誤
知道後再看就會很後怕


事務就是由一條或多條增刪改數據組成


比如我們登錄一個數據庫以後
開始一條delete語句
一個事務開始了
然後commit一個事務結束了
commit以後我們再輸入一條增刪改數據的時候
一個事務又開始了


我們可以這麼認爲一個事務的開始和結束是在兩個commit之間


我剛登陸以後
和第一個commit之間是一個事務


這個commit回車以後
接下來又輸入一些增刪改數據以後
再commit
這兩個commit之間我們叫一個事務


在提交以後


執行
SQL> delete from t1 where rownum=1;

1 row deleted.


delete刪了這個數據塊的一行數據
在內存裏刪的
刪了以後那個buffer塊就成髒塊了
buffer中的髒塊和dbf中的塊就不對應了
然後我們提交了commit


oralce有原則所有已提交事務不會丟失
提交後我們希望提交了就不會丟失了


二)事務提交方法


1)假設的方法


一種辦法是
buffer中的塊修改提交了把內存中的塊它寫到磁盤上,這個可以
然後提交成功


但是有問題
前面的例子還好一些,我只修改了一個塊
比如說我執行了delete修改了12個塊
執行了一個修改,修改了30個塊
執行了一個刪除,300個塊
而且這300多個塊分佈在磁盤的各個位置
然後這三個語句執行完了以後commit
這時候如果按照剛纔我們假設oracle需要將buffer裏面的所有的數據塊寫到磁盤上
然後commit纔會成功


commit成功就是

SQL> commit;

Commit complete.

SQL>


commit後光標返回了我們認爲就成功了


因爲它修改了這麼多的塊
這些塊分佈在buffer裏,對應在磁盤上的這些塊分佈在很多位置
commit以後
我們需要將所有的buffer寫到磁盤上
這時因爲你的buffer分佈在很多位置要做很多次尋道seek track
而且這裏還有磁盤IO的一個限制


就是我們的提交光標需要等一段時間才能返回


這個時候對用戶來講
刪除一些數據以後
然後commit,假設等了兩分鐘
我們的用戶就感覺到oracle很慢
如果用戶連到數據庫上做任何操作光標馬上返回
用戶就會認爲oracle很快
至於oracle後臺怎麼工作他不關心
不會原諒這些buffer正在往磁盤上寫所以速度比較慢
用戶就感覺你數據庫慢
我們希望的是用戶提交以後快速的返回光標

所以說我們commit以後
oracle將所有的buffer寫到磁盤上這樣不現實


2)實際的方法


在一個會話session登上來以後
執行了三條語句
第一個語句修改12個塊
第二個語句修改了30個塊
第三條語句修改了300個塊
在修改的過程會產生很多的日誌
這些日誌在這個會話的pga裏面產生


產生以後會批量的快速的寫到logbuffer裏面去
logbuffer因爲有空間限制、時間限制等等
LGWR會相對比較快速的把日誌寫到redolog裏面去


會話serverprocess修改塊的過程中產生很多日誌
日誌寫到logbuffer,logbuffer由後臺LGWR寫到磁盤上
整個過程產生的日誌都在logbuffer裏面,logbuffer也會往redolog裏寫


oracle在commit的時候
一提交這個時候oracle就會觸發LGWR把logbuffer的日誌寫到磁盤上


也就是commit的時候
commit沒有觸發DBWR將這些內存buffer中的文件將這些buffer寫回磁盤
oracle只做一件事情觸發LGWR把logbuffer寫回磁盤的redolog


好處
第一
serverprocess在修改的過程中產生的日誌寫到logbuffer裏面
logbuffer將來寫到redolog裏面去
我們在一個時間點只寫一個redolog
每一個redolog在磁盤上都是一塊連續的空間
所以說產生的日誌通過logbuffer到redolog寫的時候
尋道的次數會很少
我們產生的日誌是很集中的寫到一個redolog裏面去
而且是順序寫
它和你修改的buffer寫回dbf來的時候是離散的各個位置寫不一樣


第二
serverprocess在修改數據塊的過程中產生的日誌寫到logbuffer
在修改buffer中塊的過程中
logbuffer日誌由LGWR不停的往redolog裏寫
而且寫的速度還很快
因爲都是順序寫沒有多少尋道
當執行完了以後commit提交的時候
oracle只需觸發LGWR把剩餘的日誌寫到磁盤上就可以了


第三
日誌記錄了數據塊的所有的改變
一個數據塊改變了和磁盤上就不一樣了
我提交的時候我沒有把buffercache裏的髒塊寫回dbf
但是把髒塊的修改記錄以日誌的方式寫下來了
將來如果數據庫突然崩潰了
對磁盤數據塊來講它的修改可以通過日誌重新去做一遍


也就是對oracle來講
我們把日誌給保存起來了
相當於把對數據塊的修改也保存起來了
將來數據塊的修改如果丟失了
可以用日誌重顯出來
日誌就起這個作用的


所以我們提交的時候
oacle不需要將這麼多的塊寫回dbf
只需寫很少一塊日誌過來就ok了


這就是oracle的commit爲什麼這麼快


舉個實例
SQL> select count(*) from t1;

  COUNT(*)
----------
     50316


這個表有5萬多行


然後
SQL> delete from t1;

50316 rows deleted.


將t1表所有的數據給刪除


在這個過程中會大量的修改buffer產生大量的日誌
日誌寫到logbuffer裏面
然後被logbuffer裏的LGWR批量寫到redolog中


3)快速提交


回顧一下
客戶會話連入數據庫
給serverprocess分配PGA
sql修改數據塊產生日誌
日誌由PGA寫到logbuffer


logbuffer很小
在oracle9i以前logbuffer的大小一般不超過3M,非常小
到oracle10G以後也就是十幾兆
設大了也沒有意義浪費空間


進程LGWR把日誌從logbuffer順序的寫到日誌文件裏面去
因爲是順序的寫所以速度會很快
這就是oracle日誌的整個的一個工作過程


logbuffer一共才3M
LGWR每隔3秒鐘或者logbuffer的空間日誌超過一M的時候都會觸發LGWR往磁盤寫
所以正常情況下logbuffer裏面的日誌不會超過一個兆
也就是說logbuffer本身就很小
LGWR寫的也很快而且LGWR持續的往磁盤寫


有大量的會話連上來要修改buffer,產生大量的日誌
都寫到logbuffer裏面去
LGWR會頻繁的往磁盤寫


對其中一個會話來講
它有commit提交
這時它並不把這些buffer寫到磁盤上
提交的時候
只是把logbuffer裏面那一點點日誌給寫到日誌文件裏面去
所以說我們提交的時候速度很快


delete from t1;
刪除了很多行
塊被修改了產生了很多日誌
日誌寫回了磁盤
髒塊還在內存裏


我們現在提交一下


SQL> commit;

Commit complete.

SQL>


提交馬上就返回了


提交的過程只做一件事情
只是把logbuffer裏面的日誌清了一下
把logbuffer中的剩餘日誌寫到了redolog中
日誌往磁盤寫了一下
沒有實際把buffer寫回磁盤dbf


所以說對用戶來講
我commit速度這麼快
就認爲數據庫oracle很快
一旦光標返回,就可以做下一件事情了


這樣日誌實現了快速提交
提交非常快,馬上就認爲成功了


三)日誌和計算機緩存


前面我們說過緩存,一種是讀緩存,一種是寫緩存


計算機中
只讀緩存是把數據塊調到內存,
讀的時候可以到緩存裏面去找
cpu去讀這個塊,只能讀這個塊
如果cpu要修改這個塊,不能直接在內存修改
要修改需要直接修改磁盤上的
修改磁盤會產生IO


讀緩存只對讀有意義對寫性能很低下
它只是能提高讀的性能對寫沒有什麼性能提高


oracle因爲實現了日誌機制
修改了一個buffer塊產生logbuffer日誌馬上寫回磁盤redolog
commit以後日誌保證寫回來
commit就成功了


在oracle裏面
oracle的各種buffercache實現了寫緩存
對寫的塊和對產生的日誌寫回磁盤進行緩存
所以對oracle來講實現了寫緩存
日誌寫緩存的實現是通過日誌的buffercache也就是logbuffer
它不僅僅對讀有意義,對寫也有意義


oracle的buffercache
不僅能大幅的提高讀性能,還能提高寫性能
在整個的計算機裏面
oracle數據庫裏面能夠提供寫緩存的只有兩個地方


oracle的buffercache可以寫緩存所以說oracle的性能很高


還有一個地方
我們的數據庫都建在各種類型的存儲上,存儲有buffer,buffer上有電池
也就是存儲的buffer支持寫緩存
存儲中的單個硬盤上本身也有緩存,只提供讀緩存


在整個oracle的運行環境中
buffercache提供寫緩存
文件系統也有緩存只提供讀緩存,不能寫緩存


一般內存和磁盤的數據交換都要經過文件系統
內存的數據在從磁盤讀取時要經過文件系統的讀緩存
內存的數據在向磁盤寫入時也要經過文件系統但此時文件系統不提供緩存


當然oracle的存儲體系實際工作中很少建在文件系統上
這樣讀寫也不經操作系統的文件系統了


oracle讀數據
先從 磁盤 到 存儲的buffer 然後到文件系統的buffer 然後再到buffercache
這裏是讀緩存,讀大家都支持
所以數據一步步從磁盤到內存


oracle寫數據時
因爲redolog也在文件系統上也在存儲上
LGWR寫的時候會繞過文件系統的緩存
即繞過文件系統中的cache,這個cache只能緩存讀
直接將redolog寫到存儲的緩存裏面
然後存儲會控制在適當的時候寫到磁盤裏面去
redolog在磁盤上


存儲的寫緩存通過電池來實現的,爲了保持數據不丟失要使用電池


oracle寫數據
從內存中的logbuffer,繞過文件系統,到存儲的緩存,最後到磁盤中的redolog


我們commit成功了
實際上數據使用LGWR進程只是把數據從logbuffer寫到存儲的cache裏面去了


到底有沒有寫到磁盤上,LGWR不知道,它被存儲騙了


存儲告訴LGWR我已經寫到磁盤上了
實際它在存儲的buffer裏面
但LGWR認爲已經寫到磁盤上了


當然存儲有自己的機制來保證數據能夠寫回磁盤使數據不會丟失
如果這時出錯數據庫就會有數據丟失產生不一致


比如說存儲出問題了,電池沒電了耗完了
這時候數據也會丟失
這時候redolog也可能損壞
有這麼個地方需要大家注意


學oracle要學存儲因爲存儲中的磁盤是所有數據的最終去處


前面講了如何確保已提交的數據不會丟失
commit提交的時候
保證我這個事務所修改的所有數據塊所對應的日誌已經寫到redolog裏面去了


將來數據塊如丟了
一個事務所修改的所有數據塊所有的buffer產生的日誌都寫到redolog裏面去了
數據庫突然崩潰了,就是buffer裏面的髒塊沒了
數據庫下次啓動以後
就可以使用這些redolog把那些丟失的髒塊再重新構造出來
就是能夠將數據庫恢復到崩潰以前的那個時刻
也就是不會出現數據丟失


oracle數據庫數據恢復有 實例恢復(INSTANCE RECOVERY) 和 介質恢復(MEDIA RECOVERY)
上面說的恢復實際是實例恢復


實例恢復是Oracle實例出現失敗後,Oracle自動進行的恢復。
數據庫出現實例故障,例如:意外掉電、後臺進程故障
或預料中使用ABORT命令終止數據庫實例
在啓動數據庫時就會發現實例故障,此時就需要實例恢復
實例恢復是數據庫自動進行的,可以將數據庫恢復到故障之前的事務一致性狀態
它可以確保BUFFER CACHE中的數據不會丟失
只用到redolog,不使用歸檔日誌


介質恢復主要用於介質故障引起數據庫文件的破壞時使用
是當存放數據庫的介質出現故障時所做的恢復


介質故障是當一個文件、一個文件的一部分或磁盤不能讀寫時出現的故障
文件錯誤一般指意外的錯誤導致文件被刪除或意外事故導致文件的不一致
這些狀態下的數據庫都是不一致的,需要DBA手工來進行數據庫的恢復


介質恢復用在丟失或損壞數據文件或者丟失了控制文件的情形
將還原的數據文件恢復成當前數據文件
還能夠恢復數據文件異常脫機時沒有來得及做檢查點操作丟失的變更
介質恢復使用歸檔日誌和聯機日誌
但必須由命令顯式調用,即手工進行


如果在在線後備發現實例故障也要用介質恢復


oracle是通過日誌保證已經提交的數據不會丟失
同時也講了oracle如何實現快速的提交
一提交馬上commit成功
也給大家講了oracle如何實現寫緩存
buffercache如何實現寫緩存
LGWR繞過操作系統直接寫入磁盤,但是繞不過存儲的寫緩存



2016年10月29日

                                                                                   文字:韻箏






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章