記一次資料同步需求的改進(二)
在之前寫過 記一次資料同步需求的改進(一)之後,就開始著手對這個需求進行實踐。
所謂實踐出真知,在實際做的時候才發現可能計劃的再好,做的時候還真不是那麼回事。
在之前的郵件中已經確認目標庫是一個統計分析庫,首先拿到這個環境,先調查一番,發現了一個奇怪的現象。
檢視這個庫的歸檔情況的時候發現這個庫每天的凌晨開始要切換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';
accstat.LOAD_TEST_PROTECT_LOG(v_owner);
commit;
。。。
: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基於的是一個源端的只讀使用者,沒有物化檢視日誌的訪問許可權,所以簡單修復即可。
在統計庫中再次建立就沒有問題了。
SQL> create materialized view acc00_test_protect_log refresh fast as select * from ACC00.test_protect_log@ACC00;
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
union all
。。。
當然工作做完了,重新整理的過程還是很快的,基本十多秒回全部重新整理完成。
最後來看看改進只有的歸檔情況,藍色框中再也沒有這種抖動了。
所以問題處理還是要謹慎,細心,考慮全面,多溝通,就去能有預期的改進。
所謂實踐出真知,在實際做的時候才發現可能計劃的再好,做的時候還真不是那麼回事。
在之前的郵件中已經確認目標庫是一個統計分析庫,首先拿到這個環境,先調查一番,發現了一個奇怪的現象。
檢視這個庫的歸檔情況的時候發現這個庫每天的凌晨開始要切換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';
accstat.LOAD_TEST_PROTECT_LOG(v_owner);
commit;
。。。
: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基於的是一個源端的只讀使用者,沒有物化檢視日誌的訪問許可權,所以簡單修復即可。
在統計庫中再次建立就沒有問題了。
SQL> create materialized view acc00_test_protect_log refresh fast as select * from ACC00.test_protect_log@ACC00;
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
union all
。。。
當然工作做完了,重新整理的過程還是很快的,基本十多秒回全部重新整理完成。
最後來看看改進只有的歸檔情況,藍色框中再也沒有這種抖動了。
所以問題處理還是要謹慎,細心,考慮全面,多溝通,就去能有預期的改進。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1819981/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 記一次資料同步需求的改進(三)
- 記一次資料同步需求的改進(一)
- MySQL資料清理的需求分析和改進MySql
- 資料重新整理中的並行改進(二)並行
- 需求改進&系統設計
- 需求改進與系統設計
- 基於DataX的資料同步(下)-應用DataX進行資料同步
- 資料庫日常遇到的需求筆記(自用)資料庫筆記
- Spotify如何改進資料科學家的資料發現?資料科學
- Vuex 的非同步資料更新(小記)Vue非同步
- 利用Kettle進行資料同步(下)
- 利用Kettle進行資料同步(上)
- 團隊作業3--需求改進&系統
- 【譯】.NET 7 中的效能改進(二)
- 第二章. Dump程式的改進
- goldengate同步資料的同步速度測試記錄Go
- 記一次資料恢復資料恢復
- 記一次資料遷移
- Mybatis 學習筆記(二)——原生DAO實現資料增刪改查MyBatis筆記
- 記一次產品需求中的陣列排序方法陣列排序
- 資料重新整理中的並行改進(一)並行
- 資料重新整理中的並行改進(三)並行
- ElasticSearch + Logstash進行資料庫同步Elasticsearch資料庫
- PHP 5/Zend Engine 2.0的改進(二) (轉)PHP
- 在兩個資料庫之間進行資料同步資料庫
- 記下改變資料庫密碼的命令資料庫密碼
- 關於 es 資料同步的一次效能優化實踐優化
- 新手筆記-持續改進實踐:開發計劃的改進 (轉)筆記
- 改進的二值影像畫素標記演算法及程式實現演算法
- 單機是最好的架構之二資料同步架構
- Java程式碼質量改進之:同步物件的選擇Java物件
- 解讀記憶體資料庫的儲存需求RC記憶體資料庫
- 記錄一次產品需求中使用的一條 MySQLMySql
- 記一次資料庫hang住了資料庫
- KITTI-二進位制點雲資料集使用筆記筆記
- 團隊作業3--需求改進&系統設計
- MySQL資料庫 ---MySQL表的增刪改查(進階)MySql資料庫
- 記一次多程式同步Cookie的解惑歷程Cookie