.
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. ;)
2014. augusztus 12., kedd
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése