增量資料丟失的原因分析

dbhelper發表於2016-04-27
今天開發的同事找到我,讓我幫他們補一部分資料,因為有一個表的資料已經快一個月沒有增量資料了,這個需求聽起來有些奇怪是不?
問題的背景是在統計庫中存在一個表,供部分應用做統計分析,每天會根據時間生成一條記錄,這條記錄彙總的資料會作為統計分析所用。但是每天的這一條增量資料的源頭來自於另外兩個線上交易庫。兩個庫中的資料會做一些關聯,大體的實現思路就是下面的形式。

現在OLAP的庫中的表裡的部分增量資料沒有按照時間增加,所以對前端應用的統計造成了一定的影響。
當然對於DBA而言,這部分邏輯還是未知的,可能跨業務部門的原因,開發的同事也是一頭霧水,所以這個問題還得我來捋一捋。
有了基本的思路,這個問題的分析其實也是水到渠成。因為之前也做過類似的一些資料修補工作。
首先確定了使用者和環境,對應的表為POINT_PEIPING,而且得知每天會定時往這個表中插入資料,那麼一個很明顯的思路就是使用了scheduler或者crontab插入資料了。
crontab很容易排除了,那麼只有scheduler了。看看TEST使用者下有哪些物件。
$ sh findobj.sh TEST peiping
#################################
OWNER                OBJECT_NAME                    OBJECT_TYPE          STATUS  CREATE_DAT
-------------------- ------------------------------ -------------------- ------- ----------
TEST                 POINT_PEIPING                TABLE                VALID   2011-03-01
TEST                 PEIPING                        PROCEDURE            VALID   2011-12-02
TEST                 LOAD_PEIPING                   JOB                  VALID   2011-03-02
#################################
有了這個結果,馬上就有了思路和方向,對應的儲存過程應該是PEIPING,在JOB load_peiping中呼叫,然後把資料插入point_peiping中。
儲存過程PEIPING的程式碼為:
procedure      peiping as
begin
   insert into point_peiping_tl
   select a.created,a.remark||b.remark  from test.sum_user_point@db70 a,     test.SUM_USER_PRESENT_POINT@gcdb b
    where  trunc(a.created,'dd')=trunc(b.created,'dd')
            and a.created=to_date('20111201','yyyymmdd');
   commit;
end;
但是仔細檢視,聯絡業務資料,總是感覺哪裡不對勁,因為這個儲存過程實現不了增量的資料插入,只能滿足2011年的某一天的業務需求,所以這個儲存過程的有效性還有待驗證。
那麼我們來看看JOB的定義。
JOB的定義可以使用如下的語句得到。可以看到確實沒有使用剛所說的儲存過程PEIPING,而是直接採用了pl/sql的形式,放在了job定義裡面。從下面的這個邏輯可以很清楚的看到還是兩個資料來源,採用了db link的形式進行關聯,插入的是按照時間來界定的增量資料。
SQL>select dbms_metadata.get_ddl('PROCOBJ', 'LOAD_PEIPING',SCHEMA=>'TLBB') from dual;
BEGIN
dbms_scheduler.create_job('"LOAD_PEIPING"',
job_type=>'PLSQL_BLOCK', job_action=>
'begin
   insert into point_peiping_tl
   select a.created,a.remark||b.remark  from test.sum_user_point@db70 a,     test.SUM_USER_PRESENT_POINT@gcdb b
    where a.created >=trunc(sysdate,''dd'') and b.created>=trunc(sysdate,''dd'')
              and trunc(a.created,''dd'')=trunc(b.created,''dd'');
   commit;
end;'
, number_of_arguments=>0,
start_date=>TO_TIMESTAMP_TZ('01-MAR-2011 12.00.00.000000000 AM +08:00','DD-MON-R
RRR HH.MI.SSXFF AM TZR','NLS_DATE_LANGUAGE=english'), repeat_interval=>
'FREQ=DAILY;BYHOUR=2;BYMINUTE=0;BYSECOND=0'
, end_date=>NULL,
job_class=>'"DEFAULT_JOB_CLASS"', enabled=>FALSE, auto_drop=>FALSE,comments=>
NULL
);
dbms_scheduler.set_attribute('"LOAD_PEIPING"','logging_level',DBMS_SCHEDULER.LOG
GING_RUNS); dbms_scheduler.enable('"LOAD_PEIPING"');
COMMIT;
END;
那麼問題到此就有些奇怪了,看JOB定義也沒有問題,那為什麼增量資料會插入不了呢。
開發的同事堅稱之前是好好的,突然有一段時間就收不到資料了。當然我們還是需要驗證一下,是否這個JOB發生了些變更。
JOB執行的歷史情況可以採用下面的方式來過濾查詢。我們檢視TEST使用者在100天以內的JOB執行情況。
select log_date,owner,job_name,status,ADDITIONAL_INFO from DBA_SCHEDULER_JOB_LOG where log_date>sysdate-100 and owner='TEST' and job_name='LOAD_PEIPING' and rownum<10;
29-NOV-15 02.00.02.558857 AM +08:00 TLBB                           LOAD_PEIPING                   SUCCEEDED
01-DEC-15 02.00.02.002850 AM +08:00 TLBB                           LOAD_PEIPING                   SUCCEEDED
可以看到在去年年底的時候確實是執行成功的。
那麼現在為什麼不執行了呢,自己也花了一些時間去檢視JOB的定義和有效性是否有問題,當然還是帶著疑問檢視了最近的執行情況。
SQL>  select log_date,owner,job_name,status from DBA_SCHEDULER_JOB_LOG where log_date>sysdate-2 and owner='TLBB' and job_name='LOAD_PEIPING' and rownum<10;
02-MAR-16 02.00.00.511295 AM +08:00 TLBB                           LOAD_PEIPING                   FAILED
01-MAR-16 02.00.00.415397 AM +08:00 TLBB                           LOAD_PEIPING                   FAILED
JOB最近確實執行了,不過從執行情況來看是執行失敗了。那麼為什麼執行失敗了呢,如果這個問題能夠定義到,對於解決問題來說就是如何添翼了。
最後一頓翻箱倒櫃,發現有個檢視會定義一個概要的資訊
select * from DBA_SCHEDULER_JOB_RUN_DETAILS where log_date>sysdate-2 and owner='TEST' and job_name='LOAD_PEIPING' and rownum<10
 1662118 02-MAR-16 02.00.00.512815 AM +08:00   ORA-12541: TNS:no listener  ORA-06512: at line 2
 1661601 01-MAR-16 02.00.00.416300 AM +08:00   ORA-12541: TNS:no listener
資訊顯示在最近兩天JOB確實都執行了,但是丟擲了ORA-12541的錯誤,相關聯的一個錯誤是TNS的錯誤。
明白了這一點,排查問題就有了明確的方向,對job中涉及的db link進行連線檢查。發現確實丟擲了同樣的問題。
$ tnsping TLBB_GAMECENTER
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.127.xxxxx)(PORT = 1529))) (CONNECT_DATA = (SERVICE_NAME = gcdb)(server=dedicated)))
TNS-12541: TNS:no listener ORA-06512: at line 2       
明白了這一點之後,問題的分析就很順暢了。發現原來是某一臺OLTP的庫做了災難切換,但是在這個統計庫中沒有修改對應的連線IP地址,導致了JOB從那個時候起就不再同步增量資料了。
所以修復了這個問題之後,以後就不會擔心開發的同學每隔一段時間就找我來補資料了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2025946/,如需轉載,請註明出處,否則將追究法律責任。

相關文章