所謂實踐出真知,在實際做的時候才發現可能計劃的再好,做的時候還真不是那麼回事。
在之前的郵件中已經确認目标庫是一個統計分析庫,首先拿到這個環境,先調查一番,發現了一個奇怪的現象。
檢視這個庫的歸檔情況的時候發現這個庫每天的淩晨開始要切換20多次日志。
Redo Switch times per hour STATDB1 2015-Oct-28 11:37:52
MON DA 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
--- -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
10 25 27 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
10 26 25 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
10 27 27 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
10 28 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
可以抓取近幾天的歸檔情況的圖表來進一步驗證,每天都會如此。可以看到在特定的時間内确實都發生一些額外的資源消耗,這是非常奇怪的。
檢視DB time的情況,發現在零點的時候也會出現一個大的抖動,這個是需要格外注意的。
出于謹慎起見,準備先來分析一個這個問題,沒想到這個問題對目前的這個需求來說意義重大,也算歪打正着。
首先檢視了在問題時間段sql的DB time使用情況
SNAP_ID SQL_ID EXECUTIONS_DELTA ELAPSED_TI PER_TOTAL
---------- ------------- ---------------- ---------- ----------
37828 4yf9vjwa2yg5j 14 1433s 35%
37828 20v7cntjrscg7 1 725s 18%
37828 6yxdqb7mj3jys 5966 632s 15%
37828 d0hhst2fhvmsb 18 383s 9%
37828 1n3gxw12c2pap 12 99s 2%
然後逐個分析sql,發現sql_id 20v7cntjrscg7對應的sql竟然是一個job,每天都會嘗試全量同步一次資料,當然這個代價還是很高的
$ sh showsqltext.sh 20v7cntjrscg7
DECLARE job BINARY_INTEGER := :job; next_date TIMESTAMP WITH TIME ZONE := :mydate; broken BOOLEAN := FALSE; job_name VARCHAR2(30) := :job_name; jo
b_subname VARCHAR2(30) := :job_subname; job_owner VARCHAR2(30) := :job_owner; job_start TIMESTAMP WITH TIME ZONE := :job_start; job_scheduled_start
TIMESTAMP WITH TIME ZONE := :job_scheduled_start; window_start TIMESTAMP WITH TIME ZONE := :window_start; window_end TIMESTAMP WITH TIME ZONE := :w
indow_end; chain_id VARCHAR2(14) := :chainid; credential_owner varchar2(30) := :credown; credential_name varchar2(30) := :crednam; destination_o
wner varchar2(30) := :destown; destination_name varchar2(30) := :destnam; job_dest_id varchar2(14) := :jdestid; log_id number := :log_id; BEGIN d
eclare
v_owner varchar2(30);
begin
execute immediate 'truncate table accstat.TEST_PROTECT_LOG';
v_owner :='ACC00';
accstat.LOAD_TEST_PROTECT_LOG(v_owner);
commit;
dbms_session.close_database_link(v_owner);
v_owner :='ACC02';
。。。
:mydate := next_date; IF broken THEN :b := 1; ELSE :b := 0; END IF; END;
這個過程首先是truncate表然後開始通過db link來從各個源端來同步資料到這個表中,至于重新整理細節是在一個存儲過程LOAD_TEST_PROTECT_LOG中做的,其實所做的工作就是insert的方式,隻是使用了bulk collect,和insert all等方式進行了包裝和改進,是以每天都在默默的進行一次全量的同步,當然如果是一個簡單的性能問題也就罷了,關鍵是開發需要我同步的其中一張表就是這個job中正在同步的表,是以我産生了一些問題。
經過和開發的同僚溝通,他們對這個部分目前沒有使用需求,和同僚聊了聊,他們說印象中這種同步都是已經禁掉了,但是看來還是存在一個漏網之魚,每天都在默默的進行着同步,而且沒有使用到,想想就覺得悲涼。
是以發現了這個問題之後,開始重新審視這個需求,首先這個表是一個曆史記錄表,對于開發來說隻需要去讀取即可。然後他們需要的是增量資料,每天進行一次同步,如果按照這個需求,目前的job所做的工具已經滿足了,可以直接告訴開發需求已經滿足了即可,但是我DBA的角度來說,這個實作方式讓人感覺還是太過于浪費,每天都需要全量同步一次資料,而且資料量也不小,每天同步勢必浪費了不少的資源。而且還有一個難點比較困擾我,就是源端存在10多個使用者表,如果根據之前的需求時間字段來抽取資料,還是需要建立索引,是以這樣還需要在源端逐個建立索引,這個工作量也比較大,而且對于線上關鍵業務影響也很大。
那麼增量資料的同步還有什麼好的辦法嗎,物化視圖的增量重新整理就是一個很好的解決方案,我們隻需要在源端建立物化視圖日志即可,然後在目标端建立物化視圖,每次重新整理都采用增量的重新整理模式。這種增量和原來需求中的字段抽取方式是完全吻合的。
對于這一點,和開發同僚進行了溝通,他們非常贊同,因為不需要建立索引,而且重新整理的流程似乎更加簡單了,對于他們來說也不需要做更多的評估工作了。其實對于DBA來說也是如此。
按照這種思路實作方式就會發生改變,原來的實作方式是這樣的。
改進之後,需要建立一些物化視圖來做增量重新整理,方式就是下面的樣子。
對于這種方式。實作方式如下,具體實作的時候也碰到了一些問題。
首先需要在源端建立物化視圖日志,
> create materialized view log on acc00.test_protect_log;
Materialized view log created.
然後在目标端開始建立物化視圖。但是奇怪的是竟然報錯了。
SQL> create materialized view acc00_test_protect_log refresh fast as select * from ACC00.test_protect_log@ACC00;
create materialized view acc00_test_protect_log refresh fast as select * from ACC00.test_protect_log@ACC00
*
ERROR at line 1:
ORA-12018: following error encountered during code generation for
"ACCSTAT"."ACC00_TEST_PROTECT_LOG"
ORA-00942: table or view does not exist
Elapsed: 00:04:52.41
經過分析排查發現,db link基于的是一個源端的隻讀使用者,沒有物化視圖日志的通路權限,是以簡單修複即可。
在統計庫中再次建立就沒有問題了。
Materialized view created.
Elapsed: 00:04:41.86
然後再次嘗試重新整理就很快了,因為是增量的方式,而且資料量相對要少很多。
SQL> exec dbms_mview.refresh('acc00_test_protect_log','F');
PL/SQL procedure successfully completed.
對于其它的源端使用者表也進行了類似的操作,最開始的全量重新整理還是會消耗一些額外的資源,但是以後就不會有這樣的問題了。
最後一個問題就是對于開發人員來說,如何透明的顯示為一個test_protect_log,可以直接使用視圖來完成,因為開發隻需要讀取,不需要修改。
create or replace view accstat.test_protect_Log as
select * from ACCSTAT.ACC00_TEST_PROTECTLOG
union all
select * from ACCSTAT.ACC02_TEST_PROTECT_LOG
當然工作做完了,重新整理的過程還是很快的,基本十多秒回全部重新整理完成。
最後來看看改進隻有的歸檔情況,藍色框中再也沒有這種抖動了。
是以問題處理還是要謹慎,細心,考慮全面,多溝通,就去能有預期的改進。