Blog Johannes

Blog Johannes

johannes blog ohne logo

Blog Johannes

Zeichensatzkonvertierung mit CSALTER – funktioniert das wirklich?

Veröffentlicht: 21. Februar 2012
Geschrieben von Johannes Ahrends

In der Vergangenheit habe ich oft Projekte geleitet, bei der es um die Migration von Oracle Datenbanken ging. Vor allen Dingen Migrationen nach Linux, vereinzelt Migrationen in Richtung Standard Edition und immer wieder auch eine Zeichensatz Konvertierung Richtung Unicode.

 

In der Regel erfolgte diese Migration durch einen Neuaufbau der Zieldatenbank und anschließendem Export – Import der Daten. Dabei hat mir Quest SharePlex immer sehr geholfen, da durch die Replikation der Änderungen die Downtime für die Migration auf wenige Minuten (in der Regel der Dauer für die Umschaltung der Anwendung) beschränkt werden konnte.

Für die reine Zeichensatzkonvertierung bietet Oracle allerdings auch die Prozedur CSALTER an, also warum sollte man noch eine neue Datenbank aufbauen, wenn es doch so leicht ist, den Zeichensatz zu ändern.

Das Beispiel habe ich mit einer Oracle 11g (11.2.0.2) Datenbank auf Linux (wie bei mir üblich OEL 6) ausgeführt.

CSSCAN

Zunächst muss man die Datenbank einmal durchscannen, um eventuelle Problemfälle zu lokalisieren. Hierfür muss zunächst mit der Prozedur csminst.sql (im Verzeichnis $ORACLE_HOME/rdbms/admin) das Schema csmig angelegt werden.

Danach kann der Befehl csscan mit entsprechenden Parametern oder Interaktiv aufgerufen werden.

% csscan
Character Set Scanner v2.2 : Release 11.2.0.2.0 - Production on Tue Feb 21 16:06:32 2012
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
Username: sys as sysdba
Password:
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
(1)Full database, (2)User, (3)Table, (4)Column: 1 >
Current database character set is WE8ISO8859P15.
Enter new database character set name: > AL32UTF8
Enter array fetch buffer size: 1024000 >
Enter number of scan processes to utilize(1..64): 1 >
Enumerating tables to scan...
. process 1 scanning SYS.SOURCE$[AAAADgAABAAAAXgAAA]
...
Creating Database Scan Summary Report...
Creating Individual Exception Report...
Scanner terminated successfully.

In der Datei scan.txt findet man jetzt einige Details zum Scan. Wichtiger ist jedoch die Datei scan.err, denn hier werden die Fehler beim Scan angezeigt, also Felder oder Datentypen, bei denen die Konvertierung nicht funktioniert bzw. bei der z.B. Zeichen abgeschnitten werden. In meinem Fall sieht diese Datei so aus:

Database Scan Individual Exception Report
[Database Scan Parameters]
Parameter                      Value
------------------------------ -------------------------------
CSSCAN Version                 v2.1
Instance Name                  VMLIN11A
Database Version               11.2.0.2.0
Scan type                      Full database
Scan CHAR data?                YES
Database character set         WE8ISO8859P15
FROMCHAR                       WE8ISO8859P15
TOCHAR                         AL32UTF8
Scan NCHAR data?               NO
Array fetch buffer size        1024000
Number of processes            1
Capture convertible data?      NO
------------------------------ ------------------------------
[Data Dictionary individual exceptions]
User  : SYS
Table : SOURCE$
Column: SOURCE
Type  : VARCHAR2(4000)
Number of Exceptions         : 0
Max Post Conversion Data Size: 4000
ROWID              Exception Type Size  Cell Data(first 30 bytes)
------------------ ------------  -----  ------------------------------
AAAADgAABAAAJwOAAN convertible          --  1. Prozedur, um die Kunde
AAAADgAABAAAJwOACg convertible          -- Sequence muss in Variable
AAAADgAABAAAJwOACn convertible          -- Füllen der Tabelle Persone
AAAADgAABAAAJwPAB3 convertible          --  2. Prozedur, um die Auftr
AAAADgAABAAAJwQAAT convertible          -- Wenn die Positionentabelle
AAAADgAABAAAJwQAAU convertible          -- den Produkterecord hier zu
AAAADgAABAAAJwQABW convertible          ---     Nur für Auftraege, di
AAAADgAABAAAJwRAAL convertible          --  3. Prozedur, um die Posit
AAAADgAABAAAJwRAAq convertible          -- direkt gefüllt wird, anson
------------------ ------------------ ----- -------------------------
[Application data individual exceptions]
User  : DEMO
Table : STATUS
Column: STATUSID
Type  : CHAR(1)
Number of Exceptions         : 1
Max Post Conversion Data Size: 2
ROWID              Exception Type      Size Cell Data(first 30 bytes)
------------------ ------------------ ----- -------------------------
AAAEZmAAEAAAAEcAAA exceed column size     2 Ü
------------------ ------------------ ----- -------------------------

Okay, mit den deutschen Kommentaren in den PL/SQL Routinen komme ich klar. Wichtiger ist die letzte Zeile, denn in der Tabelle STATUS des Schemas DEMO gibt es das Feld STATUSID als CHAR(1). Die Konvertierung in AL32UTF8 benötigt für das “Ü” zwei Zeichen, das Feld ist jedoch als CHAR(1) (also 1 BYTE) definiert. Dieser Fehler muss erst behoben werden, bevor die Konvertierung weiterlaufen kann.

Okay: also zunächst die Tabelle anpassen (z.B: aus dem “Ü” ein “U” machen) und die PL/SQL Prozeduren löschen – hat man ja sowieso als Source vorliegen – oder?

Jetzt ein neuer Scan (hier als Befehl mit den Parametern):

% csscan \"sys/manager as sysdba\" FULL=Y TOCHAR=AL32UTF8 LOG=utftest ARRAY=1000000 PROCESS=1
% more utftest.errDatabase Scan Individual Exception Report
[Database Scan Parameters]
Parameter                      Value
------------------------------ -------------------------------------
CSSCAN Version                 v2.1
Instance Name                  VMLIN11A
Database Version               11.2.0.2.0
Scan type                      Full database
Scan CHAR data?                YES
Database character set         WE8ISO8859P15
FROMCHAR                       WE8ISO8859P15
TOCHAR                         AL32UTF8
Scan NCHAR data?               NO
Array fetch buffer size        1000000
Number of processes            1
Capture convertible data?      NO
------------------------------ -------------------------------------
[Data Dictionary individual exceptions]
[Application data individual exceptions]

Hurra, kein Fehler, also steht der Konvertierung auf AL32UTF8 nichts mehr im Wege.

CSALTER

Hierbei handelt es sich um eine Prozedur, die im Verzeichnis $ORACLE_HOME/rdbms/admin steht (csalter.plb). Die Prozedur holt sich alle Informationen aus den Tabellen des Schemas CSMIG. D.h. vorher muss der Befehl csscan aufgerufen worden sein und dieser Scan darf nicht älter als 7 Tage sein.

% sqlplus / as sysdba
SQL> @?/rdbms/admin/csalter.plb
0 rows created.
Function created.
Function created.
Procedure created.
This script will update the content of the Oracle Data Dictionary.
Please ensure you have a full backup before initiating this procedure.
Would you like to proceed (Y/N)?y
old   6:     if (UPPER('&conf') <> 'Y') then
new   6:     if (UPPER('y') <> 'Y') then
Checking data validity...
Sorry only one session is allowed to run this script
PL/SQL procedure successfully completed.
Checking or Converting phase did not finish successfully
No database (national) character set will be altered
CSALTER finished unsuccessfully.
PL/SQL procedure successfully completed.
0 rows deleted.
Function dropped.
Function dropped.
Procedure dropped.

Okay: erster Fehler: für den Aufruf von csalter darf kein anderen Benutzer mehr an der Datenbank angemeldet sein “Sorry only one session is allowed to run this script“. Also Datenbank herunterfahren und im Restricted Mode starten.

Danach wieder der gleiche Aufruf…
Ich erspare mir hier die Ausgabe, da ich es nicht hinbekommen habe, die Zeichensatzkonvertierung erfolgreich zum Abschluss zu bringen. Der Grund ist, dass csalter nur eine Konvertierung des Data Dictionaries durchführt und nicht der Inhalte von Tabellen. Da sich in meiner Datenbank aber “merkwürdigerweise” Daten mit Sonderzeichen (z.B. Umlaute) befinden, schlägt die Konvertierung fehl mit der Meldung: “Unrecognized convertible data found in scanner result“.
Erst nachdem ich die Schema mit den Daten gelöscht hatte, war eine Konvertierung möglich – aber wer braucht das schon.

An dieser Stelle wäre ich sehr an einer Diskussion interessiert. Vielleicht war ja jemand erfolgreicher als ich. Für mich gilt jedoch weiterhin: bei einer Migration eine neue Datenbank aufzubauen und die Daten per Export / Import (ob DataPump oder wie auch immer) zu übertragen. In meinem nächsten Blog werde ich aber noch einmal auf das Thema Umlaute bei UTF8 und maximale Anzahl von Zeichen zu sprechen kommen.

Johannes Ahrends

CarajanDB GmbH

Siemensstr. 25  50374 Erftstadt

Fon: +49 (2235) 170 91 83

Fax: +49 (2235) 170 79 78

Mail: info@carajandb.com

 

carajan-db-logo