天天看點

增量資料丢失的原因分析

今天開發的同僚找到我,讓我幫他們補一部分資料,因為有一個表的資料已經快一個月沒有增量資料了,這個需求聽起來有些奇怪是不?

問題的背景是在統計庫中存在一個表,供部分應用做統計分析,每天會根據時間生成一條記錄,這條記錄彙總的資料會作為統計分析所用。但是每天的這一條增量資料的源頭來自于另外兩個線上交易庫。兩個庫中的資料會做一些關聯,大體的實作思路就是下面的形式。

增量資料丢失的原因分析

現在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

    where a.created >=trunc(sysdate,''dd'') and b.created>=trunc(sysdate,''dd'')

              and trunc(a.created,''dd'')=trunc(b.created,''dd'');

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從那個時候起就不再同步增量資料了。

是以修複了這個問題之後,以後就不會擔心開發的同學每隔一段時間就找我來補資料了。