一、怎么樣刷新
mv可以用來(lái)同步數據,一般采用主鍵同步或者是ROWID同步,我們這里只討論主鍵同步(Rowid同步其實(shí)是為Rowid在目標表上創(chuàng )建了一個(gè)隱含索引,原理跟主鍵同步一樣)。mv的主要原理就是記錄更改的日志,并同步到遠程。
一個(gè)簡(jiǎn)單的例子:
- SQL>create materialized view log on table_name;
- SQL>create materialized view table_name [on prebuilt table] refresh fast as
- select * from table_name@lnk_db_master;
- SQL>exec dbms_mview.refresh('table_name',method => 'Complete');
- SQL>exec dbms_mview.refresh('table_name');
- SQL> declare jobid number;
- begin
- sys.dbms_job.submit(job => jobid,
- what => 'dbms_mview.refresh(''table_name'');',
- next_date => sysdate,
- interval => 'sysdate+5/1440');
- commit;
- end;
- /
其中
第1步是在需要復制的主表(master table)上創(chuàng )建mv log。
第2步是在遠程站點(diǎn)(想復制到的那個(gè)站點(diǎn))上創(chuàng )建mv,注意,如果選擇了選項on prebuild table的話(huà),表示在已經(jīng)存在的表上創(chuàng )建mv,需要已經(jīng)存在的表的字段與select的字段必須要對應,這個(gè)已經(jīng)存在的表中可以沒(méi)有數據。
第3步是全同步,如果沒(méi)有選擇on prebuild table,這一步可以省略,因為默認創(chuàng )建mv的時(shí)候,就會(huì )全刷新
第4步是增量刷新,在完成全刷新以后的情況下,一般都只需要做增量刷新即可。
第5步是創(chuàng )建一個(gè)自動(dòng)刷新的作業(yè)來(lái)進(jìn)行刷新,如每5分鐘刷新一次,這個(gè)操作也可以同crontab來(lái)代替。
二、相關(guān)視圖與基表信息
dba_mviews記錄了遠程站點(diǎn)上mv的數目與屬性,需要在創(chuàng )建MV的站點(diǎn)上查詢(xún)。
sys.mlog$則記錄了主站點(diǎn)上的mv的log數目,如果一個(gè)master對應到多個(gè)站點(diǎn),也只有一條記錄,對應到dba_mview_logs視圖,需要在主站點(diǎn)查詢(xún)。
sys.slog$記錄了主站點(diǎn)上已經(jīng)注冊成功的主表信息,如果一個(gè)主表被復制到多個(gè)站點(diǎn),則對應多條記錄,在主站點(diǎn)查詢(xún)。
dba_snapshot_logs存放了mv的log日志,如果對應到多個(gè)站點(diǎn),則每個(gè)站點(diǎn)都對應一條記錄,因為遠程站點(diǎn)的snapshot_id是不一樣的。其實(shí)sys.mlog$與sys.slog$的關(guān)聯(lián)就是組成dba_snapshot_logs的一個(gè)部分,通過(guò)查詢(xún)dba_views可以看到其腳本。
dba_registered_snapshots記錄了遠程站點(diǎn)的注冊信息,只記錄注冊成功的遠程站點(diǎn),通過(guò)snapshot_id可以與dba_snapshot_logs關(guān)聯(lián)。如
- SQL>select t.log_owner,t.master,t.log_table,t.current_snapshots,
- r.owner,r.name,r.snapshot_site
- from dba_snapshot_logs t,dba_registered_snapshots r
- where t.snapshot_id= r.snapshot_id(+);
刪除mv的時(shí)候,需要先刪除mv,再刪除mv日志
遠程MV站點(diǎn):
- SQL>drop materialized view table_name;
主站點(diǎn):
- SQL>drop materialized view log on table_name;
注意,刪除mv的時(shí)候,如果主站點(diǎn)需要分發(fā)到多個(gè)遠程站點(diǎn),只有當所有遠程站點(diǎn)的MV刪除完成后,才可以刪除MV日志。
刪除遠程站點(diǎn)的MV的時(shí)候,要保證與主站點(diǎn)的通信順暢,如果網(wǎng)絡(luò )不通,則主站點(diǎn)無(wú)法正常Unregister MV,而主站點(diǎn)的mv log又因為不知道這個(gè)站點(diǎn)已經(jīng)沒(méi)有MV,而不刪除mv日志,將可能引起主站點(diǎn)mlog表的膨脹。這個(gè)時(shí)候,可以手工強行解除注冊。
- SQL>exec DBMS_SNAPSHOT.PURGE_SNAPSHOT_FROM_LOG (snapshot_id);
三、故障處理與維護
如果mlog因為日志曾經(jīng)很多而變得很大的時(shí)候,對mlog的操作如日志刪除將變得很慢,因為mlog上沒(méi)有任何索引,走的都是全表掃描,這個(gè)時(shí)候,我們可以move該日志表或者是等日志表沒(méi)有記錄的時(shí)候truncate該表。
- SQL>alter table mlog$_table_name move;
如果要對有mv復制的表增加字段,最好在停機情況下進(jìn)行,因為這樣不會(huì )產(chǎn)生mv log,而且最好采用prebuild模式,因為這種模式下,刪除mv的定義將保留表(也就是不刪除表與相關(guān)數據)。相關(guān)步驟:
停機模式,并且在使用prebuild的情況下:
1、遠程站點(diǎn):
- SQL>drop materialized view mv_table; --這里刪除mv,保留原表
2、主站點(diǎn):
- SQL>alter table master_table add new_field number;
3、遠程站點(diǎn):
- SQL>alter table mv_table add new_field number;
4、遠程站點(diǎn):
- SQL>create materialized view mv_table on prebuilt table
- refresh fast as
- select * from master_table@lnk_db;
5、建立快速刷新的作業(yè),這個(gè)時(shí)候不需要全刷新了,因為數據都在
為什么要停機操作,是因為創(chuàng )建快速刷新的mv的時(shí)候,將刪除主站點(diǎn)上創(chuàng )建mv時(shí)間點(diǎn)之前的相關(guān)log,所以在刪除mv與重新創(chuàng )建mv之前,不能對主表有任何dml產(chǎn)生新的日志,否則將可能引發(fā)數據的不一致。