理解UNDO-1
2017-02-23 曾凡坤-小凡仙 曾凡坤一小凡仙
UNDO在ORACLE 裡面是非常重要的元件,也是ORACLE能競爭過MSSQL,IBM等資料庫的重要優勢.後來MYSQL資料庫的 innodb引撐也加入了UNDO特色.
UNDO是什麼? 業界的叫法很多,中文名詞也很多,然後對於理解它反而造成了混亂. 什麼前滾,撤銷,回滾.
實際上UNDO 就是UNDO .它只是暫時儲存下過去的東西而已, 一個表空間.
好比我們要做某些事情需要臨時空間來操作,也許叫工作空間. 當然我們的ORACLE也有個臨時表空間. 不過我們的資料庫裡的資料很重要,幹活之前得把原來的資料放在另外個地方儲存起來.等活幹好了,幹完了,得到領導肯定的好評.那就可以把新資料存進資料庫裡面,原來的資料就可以廢棄了!
所以UNDO實際修改資料臨時把原來的資料存放的表空間, 太長了,簡短說是,舊資料表空間!
那好了 我們有了舊資料表空間,保留舊資料可以幹什麼呢? 其實我們想到幹什麼就能幹什麼.
目前能幹下面的事
1 我們活幹失敗了,領導不滿意, 就要把資料恢復過來,或者叫還原回來
2 我們幹活當中,是有個時間長度的,最小也要毫秒的時間.這個時候,別人來查資料,如果沒有舊資料,那他該查什麼呢? 等你活幹完了,看新的資料嗎? 可新資料不是他想要的.
好了 我們把上面1和2 拿資料庫術語來說是
1 事務回滾 ROLLBACK,實列恢復. 實列恢復不僅需要REDO日誌,也需要UNDO來參與
2 這叫讀一致性,不能讀髒,不能讀已提交, CR塊.ACID
一個事務的開始需要從UNDO裡面要到東西才能幹活. 得先獲得UNDO表空間裡的塊.
事務叫做一系列的操作,可以通俗理解工作內容,工作步驟,工作流程. 翻譯成IT術語就是一些列的SQL.
如果你寫過儲存過程的話,可以理解一個儲存過程就一個事務單位.
所以UNDO和事務是掛勾的, 事務需要在UNDO裡存放舊資料. 涉及到事務的地方有兩個,一個是UNDO裡面,另外一個是資料塊裡面的ITL槽. 叫做事務槽.
我們給事務分配個ID, 這個ID不是自增量,也不是時間量,而是跟UNDO有關的.
我們執行個事務如下:
update zfk set object_name=’zfk’ where object_id=9;
不提交它,然後查詢事務表V
XID 05001B00DEAF000 是十六進位制的事務ID
它是由 XIDUSN.XIDSLOT.XIDSQN組成的. 把值轉換成16進位制 5=>05; 27=>1B;45022=>AFDE . 然這個值是反的.
這三個是什麼呢? XIDUSN是UNDO段編號, XIDSLOT是段裡面的事務槽編號,XIDSQN是該事務槽中第幾次被重用. 也就是重用次數.
從上面XID的編碼可以推算出,同時活躍的XID多少? 取決於UNDO表空間裡的段多少,以及每個段裡面的事務槽是多少.
在10G以後,UNDO採用自動管理模式,下圖是系統自動生成的10個段.另外一個是SYSTME的
來我們看看UNDO段,段頭塊裡面的資訊
這個圖只是讓大家在大腦裡有個映像而已,重點看事務控制區,事務表和空閒塊.
這篇不詳細講事務的事情! 我們主題是UNDO嘛!!
UNDO段很多人把它做成圓圈形式,我覺得容易誤解人,還有這個前值映像.
UNDO 裡面的段,段中的塊會反覆地重用! 不僅是重用而且 要覆蓋舊資料.
這就容易導致 ORA-01555 快照太舊. 結合上面的圖好像是時鐘樣,轉一圈,不管三七二十一就把前面的塊給覆蓋掉了.不是這樣的感覺的.
從UNDO段頭的塊裡面看到有個空閒塊池! 那麼這就涉及兩個問題, 問題一就是事務槽的事務被重用,另外個是UNDO塊的重用.是兩個不同物件的重用.
ORACLE 對UNDO 塊的重用是有條件的, 優先使用空閒塊,否則就擴充套件,再者重用!
應像這圖樣在大腦裡形成映像, 灰色的代表已經使用的UNDO塊,綠色代表是未使用的塊,叫空閒塊.
因此UNDO表空間中的資料在不同時段就會有不同的狀態顯示,在dba_undo_extents 資料字典裡記錄了UNDO中每個區段的狀態.
SQL> SELECT tablespace_name, status, SUM (bytes) / 1024 / 1024 as “Bytes(M)”
FROM dba_undo_extents
GROUP BY tablespace_name, status;
TABLESPACE_NAME STATUS Bytes(M)
UNDOTBS2 EXPIRED 1.4375
UNDOTBS2 UNEXPIRED .375
UNDOTBS2 ACTIVE .125
UNDOTBS1 EXPIRED 22
其中:
ACTIVE :未提交的事務所佔用的UNDO塊,該塊所關聯的事務並未提交,用於實現讀一致性,所以該資料不能被其它事務的資料所覆蓋 。
UNEXPIRED:已經提交但未過期的UNDO塊,該UNDO塊關聯的事務已經提交,但是仍受到undo retention引數保持時間的影響,當undo表空間中沒有可用的資料塊時,這些資料塊會直接被覆蓋而進行重用。
EXPIRED: 事務已經提交,而且UNDO塊儲存時間已經超過undo retention引數指定的時間,屬於已經過期的資料.可以被隨時重用。
需要說明的是,當設定表空間啟動Guarantee特性時,UNEXPIRED型別的塊就必須要等到undo_retention 指定時間過期後才能被重用。
這個UNDO段沒有空閒塊了,那隻好重用某些塊了! 那到底重用哪些UNDO塊呢?
仔細閱讀上面的文字可以理清下.
實際上我們通過紅綠燈來表示
1 優先重用綠色的 EXPIRED
2 接著重用 黃色的 RETENTION 保護期900秒中的塊. 當然你可以制定規則,不可以重用黃色的.你可以使用ALTER TABLESPACE undotbs1 RETENTION GUARANTEE 修改UNDO表空間的屬性,強制黃色的不能重用
3 從其他的UNDO段裡偷空閒的UNDO塊用
另外說下 11G有個討厭的引數如下
–設定UNDO自動調優,它會使的UNDO長期得不到釋放
alter system set “_undo_autotune” = flase scope=spfile;
一般來說UNDO表空間給一個數據檔案,在LINUX下能擴充套件到32GB,基本上能滿足所有的業務.
然並卵的事情,32GB UNDO也要使用掉,ORACLE很貪吃的, 按照上面的原則基本上先擴充套件後重用,也就是說32GB過不鳥幾個月就到達了.UNDO空間使用率100% 其實這個沒啥關係,除非你的磁碟空間真心的少,不夠用的話,只要新建個UNDO表空間,再進行空間切換,釋放舊的UNDO空間的磁碟大小.
再說下 一個事務申請一個UNDO塊來使用, 這個時候是以獨佔模式霸佔整個塊. 也就是說該UNDO塊只要它一個事務可以寫,其他事務不可以寫. 只有等它寫完了,還有空閒的空間,別的事務就可以寫.
另外一個事務,只能在一個UNDO段裡面工作,原則上不可以跨段,使用別的段裡的UNDO塊.
這就是說事務最多使用的UNDO塊數量,取決於UNDO段. 超過了就容易報
ORA-1628 回滾段達到32765最大值
也就是說我們要控制事務的大小,不能讓它產生太多舊資料了,方法是分批修改資料.
這裡再談下前值映像. 很早以前,我一致認為是整個資料塊,儲存在UNDO裡面,否則UNDO使用那麼多呢? 這個前值映像真的不好理解,它實際上就是 該列的原值. 不是塊,也不是一整行.
ORA-01555 快照太舊 這個錯誤是怎麼回事呢? 其實這個錯誤在很早以前大約10年前吧,還挺流行的. 意思是說我要的舊資料找不到了,被重用了!
大家一看到是被重用了,就是手UNDO段要麼太小了,只有不夠用,不能擴展才開始重用.要麼是事務太頻繁了. 這個是什麼意思呢? 也就是說事務非常多,在不能擴充套件的情況下,事務需要重用塊.很不幸你需要的塊被中招重用了.
這要從多方面優化, 1 是增加UNDO表空間大小.2優化你自己的查詢語句或者其他DML語句.讓其查詢時間變短; 3 是優化大事務,讓其使用更少的塊.