Magamról

Saját fotó
Főiskolai, majd egyetemi diplomamunkáimtól kezdve világ életemben, adatok, adatbázisok, adattárházak (leginkább Oracle) környékén mozogtam. Mostanság adattárházasként, adatbányászként élem napjaimat.

2014. augusztus 12., kedd

ORA-29275: partial multibyte character

.
Feladat: 
Adott két Oracle-instance (egy ERP és egy analitikus célú adatpiac) közte Informatica ETL tölti az adatokat. Az ETL session-logja tartalmazza a címbeli hibaüzenetet. 

Egyéb infók:
- Sehol semmilyen jogosultság nincs, csak és kizárólag select jog az adatbázisokban.
- Brutális méretű view adatait kell átemelnie az ETL-nek,  45 millió rekord 162 nagyrészt karakteres oszlop.
- Csak varchar2 oszlop van, nincs nvarchar2.
- Az ETL 4 óra futás után hal meg (hogy az időviszonyokat lehessen érzékelni) és mivel batch jellegű így sorazonosító értelemszerűen nincsen a hibaelőfordulásnál.

Hol lehet a hiba, milyen kérdések sorjáznak?
(A) ERP DB oldalon. Ki tud segíteni? Kinek kell segíteni? Fejlesztő? DBA? Alkalmazás-oldali vagy DB-oldali a hiba?
(B) Informatica oldalon. Reprodukálható-e a hiba Informaticán kívül is? Ha Informaticán kívül nem reprdoukálható a hiba, akkor Informatica oldalon célszerű keresni? Ha az Informatica a session logjában forrás-oldali hibát ír, akkot tényleg olvasási probléma van, vagy cél-adatbázis írási?

Gyári hibaüzenet:
ORA-29275: partial multibyte character
Cause: The requested read operation could not complete because a partial multibyte character was found at the end of the input.
Action: Ensure that the complete multibyte character is sent from the remote server and retry the operation. Or read the partial multibyte character as RAW.


1.Megoldás-csokor (Oracle felöl)
A Google-kereső rögtön első helyen ezt a találatot hozza.
ORA-29275 Tips

Gyors ellenőrzés a forrás és cél adatbázisokban:
SELECT * FROM v$nls_parameters

Rögtön látszik, hogy forrás-oldalon UTF8, céloldalon: AL32UTF8

Rögtön kézenfekvően látszik, hogy a Google-adta tipp CONVERT-jét érdemes megpróbálni. Persze minél inteligensebb formában a méretek miatt. Sok adat, kicsi SPOOL (1 MB).

- Bulk collect alkalmazása limit-tel (én 10.000-es adagokat használtam). Ez egyszer végignyalja az egész adattömeget, bitről-bitre és úgy firtatja, ahogy kell (convert)

- Természetesen az összes karakteres oszlopra kell ezt nézni, de én a blog miatt ezt egyszerűsítettem egy oszlopra.

DECLARE
  CURSOR cur_tabla IS
  SELECT *
  FROM tabla ;
  TYPE type_tabla IS TABLE OF tabla%ROWTYPE INDEX BY PLS_INTEGER;
  list_tabla type_tabla;
  iLimit INTEGER:=10000;
  iMi INTEGER:=0;
  strTmp VARCHAR2(32767);
BEGIN
  OPEN cur_tabla;
  LOOP
    iMi:=iMi+1;
    DBMS_OUTPUT.PUT_LINE(iMi);

    FETCH cur_tabla
    BULK COLLECT INTO list_tabla
    LIMIT iLimit;

    FOR indx IN 1..list_tabla.COUNT LOOP
      BEGIN
        strTmp:=CONVERT(list_tabla(indx).je_line_description,'UTF8','AL32UTF8');
      EXCEPTION
        WHEN OTHERS THEN
          dbms_output.put_line(list_tabla(indx).row_id);
      END;
    END LOOP;

    EXIT WHEN list_tabla.COUNT < iLimit;
  END LOOP;
  CLOSE cur_tabla;
END;


De a legjobb/legszebb megoldásnak a kollégám megoldását tartom (ugyanis nem igényel tárolt eljárást):

SELECT *
FROM
(
  SELECT
    CASE
      WHEN description != description || '' 
      THEN 'DESCRIPTION'
      WHEN status != status || '' 
      THEN 'STATUS'
      [összes többi varchar oszlop…]
    END col,
    rowid rid
  FROM tabla
)
WHERE col IS NOT NULL;


Megoldás a select dump() használata is. Az is megmutathatja, hogy valami nem fain a karakteres tárolásban. De messze ez a leginkább low-level, legkevésbé elegáns.



2.Megoldás (Informatica felöl) 

Az Informatica természetesen képes röptiben kezelni az UTF-verziókat. Nálunk is ez adta a végső megoldást. ;)

Nincsenek megjegyzések:

Megjegyzés küldése