Blog Johannes

Blog Johannes

johannes blog ohne logo

Blog Johannes

Oracle 12c Unicode Migration

Veröffentlicht: 10. September 2013
Geschrieben von Johannes Ahrends

1. Migration Szenarios

In den vergangenen Jahren habe ich unterschiedliche Oracle Datenbank Migrationen betreut, die Gründe dafür waren: Plattformwechsel (z.B. HP/UX nach Linux), Wechsel der Oracle Edition (in der Regel von Enterprise auf Standard Edition) oder die Umstellung des Zeichensatzes auf Unicode. Die einfachste Migration stellt in der Regel der Plattformwechsel dar, weil Oracle mit Transportable Tablespaces, Cross-Plattform Backups oder DataGuard eine Reihe von sehr hilfreichen Funktionen zur Verfügung stellt. Natürlich sind, je nach Verfahren, kürzere oder längere Auszeiten notwendig aber die Vorgehensweise ist gut dokumentiert und getestet.

Wenn Sie allerdings planen, von der Enterprise auf die Standard Edition zu wechseln, dann gibt es derzeit nur den Weg über das Entladen und Laden mit Oracle Data Pump. Zwar ist das nicht sehr kompliziert, allerdings haben wir es zunächst einmal mit einer sehr großen Downtime der Anwendung zu tun. Wenn dann noch zusätzliche Anforderungen, wie der Wechsel des Zeichensatzes auf Unicode dazu kommt, wird es anspruchsvoll und fehleranfällig. In diesem Fall raten wir dazu, dass Sie sich mit dem Thema "Minimal Downtime Migration", d.h. dem Einsatz einer Replikationslösung für die Synchronisierung der Datenbanken während der Migration, beschäftigen.

1.1 Minimum Downtime Migration

Zwar geben die Replikationssoftware-Hersteller gerne an, dass Sie Live Migration oder "Zero Downtime Migration" können, aber ich bin da pessimistisch. Nicht weil die Software das nicht prinzipiell könnte, sondern weil ich in den mehr als 10 Jahren, seit ich dieses Thema betreue, nur ein einziges Mal erlebt habe, dass eine Migration im laufenden Betrieb, d.h. ohne dass die Anwendung gestoppt werden musste, geklappt hat. In der Regel wird eine Downtime notwendig sein, weil Web- und Applicationserver umgestellt, TNS-Aliase geändert oder Router neu konfiguriert werden müssen. Daher vermeide ich den Begriff "Live Migration" und spreche lieber von einer Minimal Downtime Migration, die in der Regel mit einer Auszeit der Anwendung von 10 bis 30 Minuten verbunden ist.

Selbst wenn Transportable Tablespaces und Cross-Plattform Backups interessante Alternativen bei der Plattform Migration sind, ziehe ich die Methode DataPump Export / Import und Replikation vor, weil dadurch einfacher getestet werden kann und außerdem die derzeitige Produktion geringer belastet ist.

1.2 Unicode Migration

Oracle bietet seit Jahren Hilfsmittel für den Wechsel des Zeichensatzes an. Ursprünglich mit cscan und csalter gibt es seit ca. 2 Jahren das Tool "DMU" (Data Migrator for Unicode). Dieses grafische Werkzeug scannt die Datenbank nach Sonderzeichen, die geändert werden müssen und liefert zusätzlich auch noch Informationen über fehlerhafte Zeichen oder zu lange Zeichenketten. Falls es keine Probleme gibt, kann der Zeichensatz in der vorhandenen Datenbank geändert werden - allerdings gibt es in den meisten Fällen Fehler! Generell vertrete ich die Ansicht, dass solch schwerwiegende Änderungen nicht einfach so durchgeführt werden sollten, daher würde ich bei einer Unicode Migration genau wie bei der Migration von Enterprise auf Standard Edition zu einem Data Pump Export / Import verbunden mit einer Replikation raten.

2. Meine Regeln bei einer Migration

  1. Ändern Sie so wenig wie möglich an dem Produktionssystem. Der Aufbau einer neuen Datenbank auf einem neuen Rechner ermöglicht Ihnen einen umfangreichen QA Test mit Produktionsdaten.
  2. Bereiten Sie auf dem neuen System (Rechner / Datenbank) alles vor, bevor umgeschaltet wird.
  3. Testen Sie die neue Datenbank mit unterschiedlichen Anwendungen und auch mit Toad. Dadurch erkennen Sie hoffentlich frühzeitig, ob Sie "Schmutzzeichen" haben.
  4. Minimieren Sie die Downtime für die Produktion. Auch wenn das Zeitfenster 24 oder 48 Stunden beträgt und die Migration nicht länger als 12 Stunden dauern sollte. Beachten Sie, dass Sie unter Umständen im Fehlerfall z.B. durch eine Datenkorruption die komplette Datenbank wieder herstellen müssen. Kalkulieren Sie die Zeit für den Restore in Ihre Downtime mit ein und beachten Sie, dass Sie dann wieder bei "Guten Morgen" sind, d.h. sie müssen ein neues Maintenance Fenster beantragen, etc.

Aufgrund dieser Regeln rate ich dazu, eine Replikationslösung wie DELL Shareplex for Oracle oder Dbvisit Replicat während der Migration einer Oracle Datenbank zu nutzen, unabhängig davon, ob es sich um einen Plattformwechsel, einen Editionswechsel oder die Unicode Migration handelt. Sicherlich sind hiermit zunächst einmal höhere Kosten verbunden aber beachten Sie bitte meine 4. Regel: was kostet es Sie, wenn zwei Oracle DBAs ein gesamtes Wochenende arbeiten müssen (nachdem Sie es beim Betriebsrat durchgesetzt haben) und Sie stellen kurz vor Ende der Migration fest, dass es einen Fehler gibt. Diese Kosten und der damit verbundene Aufwand rechtfertigt in den meisten Fällen den Einsatz einer Replikationslösung. Noch dazu, da beide genannten Hersteller für ihre Software Projektpreise bieten, d.h. keine perpetual License sondern nur eine Miete für die Dauer der Migration. 

Ein letzter und vielleicht wichtigster Grund für den Einsatz einer Replikationssoftware: Sie haben im Vorfeld der Migration Zeit für Test und sie haben, durch die Umkehrung der Migration von der neuen Plattform auf die alte auch noch einen Fallback, falls die Anwendung nicht so arbeitet, wie erwartet.

2.1 Stolperfallen bei einer Unicode Migration

Es gibt zwei große Probleme bei der Unicode Migration:

  1. Eine "falsche" Datentyp-Definition
  2. Die Grenzen der Datenbank

Ist dies ein gültiger DDL-Befehl?

CREATE TABLE kunden (
kundid     NUMBER(10)   GENERATED BY DEFAULT AS IDENTITY,
anrede     VARCHAR2(5),
vorname    VARCHAR2(20),
nachname   VARCHAR2(20),
geburtstag DATE);

Ja und Nein: Der Befehl ist sicherlich gültig. Oracle wird sich nicht beschweren und die Tabelle wird erstellt. Die Anwendung kann Daten eingeben, solange die maximale Länge eines Feldes nicht überschritten wird. Aber was ist hiermit:

SQL> INSERT INTO kunden (anrede, vorname, nachname)
     VALUES ('Herr','Mike','Mülleimeraussteller');

Sie bekommen die folgende Fehlermeldung:

VALUES ('Herr','Mike','Mülleimeraussteller')
                   *
ERROR at line 2:
ORA-12899: value too large for column "DEMO"."KUNDEN"."NACHNAME" (actual: 21, maximum: 20)

Aber die Definition sagt doch, dass der Nachname 20 Zeichen lang sein darf und "Mülleinerausteller" sind genau 20 Zeichen. Der Grund hierfür ist, dass der Umlaut "ü" in der Unicode Codierung zwei Byte belegt, die Spalte "nachname" aber mit 20 Byte und nicht 20 CHAR angelegt wurde. Die Antwort auf die Frage, ob der DDL-Befehl gültig ist, muss also lauten "Nein", denn in unserem Sprachraum werden 20 Zeichen und nicht 20 Byte benötigt. Um den Fehler zu beheben bzw. um einen gültigen DDL-Befehl zu erhalten, sollten Sie es wie folgt ändern:

CREATE TABLE kunden (
kundid     NUMBER(10)   GENERATED BY DEFAULT AS IDENTITY,
anrede     VARCHAR2(5 CHAR),
vorname    VARCHAR2(20 CHAR),
nachname   VARCHAR2(20 CHAR),
geburtstag DATE);

Jetzt funktioniert auch der Insert:

SQL> INSERT INTO kunden (anrede, vorname, nachname)
2   VALUES ('Herr','Mike','Mülleimeraussteller');

1 row created.

Wie wirkt sich das auf die Unicode Migration aus? In den meisten Fällen haben die Anwendungsentwickler sich wahrscheinlich keine Gedanken über Multibyte Zeichensätze gemacht, d.h. alle CHAR und VARCHAR2 Felder wurden mit der Längensemantik "BYTE" angelegt, das ist ja bei einem ein Byte Zeichensatz, wie WE8ISO8859P15, in Ordnung. Leider ist es nicht möglich, diese Längensemantik während eines Export / Import Prozesses (egal ob mit DataPump oder nicht) zu ändern. Die einzige Möglichkeit besteht darin, die Tabellen mit der korrekten Längensemantik vor dem Import zu erstellen und dann die Daten zu importieren. Toad for Oracle kann hier ganz einfach helfen, weil es mit der Option “Include Byte/Char spec when creating DDL scripts from 9i databases” die Möglichkeit gibt, die Längensemantik ein- bzw. auszuschalten. 

JA-Blog-090913-1

D.h. man lässt sich, entgegen meines vorherigen Beispiels, die DDL-Befehle ohne Längensemantik generieren und fügt dann einfach am Anfang des Skriptes die Längensemantik hinzu:

ALTER SESSION SET NLS_LENGTH_SEMANTICS='CHAR';
--
-- Create Schema Script
--   Database Version         : 11.2.0.3.5
…

Bitte setzen Sie den Parameter nur auf Session und nicht auf Datenbankebene. Auch wenn das prinzipiell erlaubt ist, gibt es immer mal wieder Probleme mit Patches, etc., weil dann Data Dictionary Objekte mit der "falschen" Längensemantik angelegt werden. Im My Oracle Support finden Sie dazu auch weitere Hinweise.

Aber was ist mit dem zweiten Problem: Die Grenzen der Datenbank? Lassen Sie uns zunächst davon ausgehen, dass wir ein Feld "DESCRIPTION" haben, dass als VARCHAR2(4000) angelegt wurde. Mit der Unicode Umstellung haben wir daraus ein VARCHAR2(4000 CHAR) gemacht, also alles in Ordnung!?

ALTER TABLE customer
ADD DESCRIPTION VARCHAR2(4000 CHAR);

Wie viele Zeichen können in diesem Feld gespeichert werden? 4000! ... nur wenn es ausschließlich ein Byte Zeichen sind. Die Grenze der Datenbank für VARCHAR2 sind 4000 BYTE und nicht 4000 CHAR. Wenn Sie diese Grenze erreichen, müssen Sie entweder auf den Datentyp CLOB wechseln oder sie verwenden den Extended Datatype von Oracle 12c.

2.2 VARCHAR2(32k) in Oracle 12c

Wenn man sich die Oracle 12c Dokumentation ansieht, dann kann man zu dem Schluss kommen, dass man jetzt tatsächlich ein Feld mit VARCHAR2(4000 CHAR) anlegen kann, egal ob ein-Byte oder Multibyte. Allerdings ist das nur teilweise richtig. Zunächst gilt auch in der Oracle 12c Datenbank die Limitierung von 4000 BYTE für VARCHAR2. Aber man kann einen Upgrade (!) durchführen, der anschließend die Verwendung von VARCHAR2(32767) erlaubt.

SQL> SHUTDOWN IMMEDIATE
SQL> STARTUP UPGRADE
SQL> ALTER DATABASE OPEN MIGRATE; -- Only the Pluggable Database
SQL> ALTER SYSTEM SET MAX_STRING_SIZE=EXTENDED;
SQL> @?/rdbms/admin/utl32k.sql

Jetzt kann man ohne weitere Änderung tatsächlich 4000 Zeichen in das entsprechende Feld einfügen, egal ob ein-Byte oder Multibyte.

Man muss allerdings beachten, dass es nur so aussieht, als würde ein VARCHAR2 Feld verwendet. Intern werden die Felder, die länger sind als 4000 Byte als BLOB verwaltet. Zwar ist das der Entwendung egal, dafür hat Oracle gesorgt, allerdings kann die Angabe der Größe einer Tabelle (z.B. BLOCKS in USER_TABLES) jetzt fehlerhaft sein, weil das Feld "DESCRIPTION" gar nicht mit in der Tabelle sondern als LOB-Objekt gespeichert wird. Mehr dazu in meinem Blog "VARCHAR2(32767) - Sinn oder Unsinn?".

JA-Blog-090913-2

Dennoch ist diese Möglichkeit ein weiterer Schritt hin zu einer einfachen Unicode Migration.

2.3 Was sind "Schmutzzeichen"?

Zunächst hört es sich an, als wäre das eine Datenkorrumpierung, wenn fehlerhafte Zeichen in der Datenbank landen. Leider ist dem jedoch nicht so, sondern es handelt sich in der Regel um einen Programmierfehler, weil sich der/die entsprechende(n) Entwickler nicht mit den Zeichensätzen auskannten. Wenn man einmal annimmt, die Datenbank wäre mit dem US7ASCII Zeichensatz aufgesetzt worden, dann könnte man davon ausgehen, dass, wenn man auf Anwendungsseite als Parameter NLS_LANG ebenfalls US7ASCII einträgt, beide Zeichensätze (Client und Server) übereinstimmen. Dem ist aber nicht so. Mit der Variablen "NLS_LANG=GERMAN_GERMANY.US7ASCII" wird nur dem Oracle Net mitgeteilt, dass keine Zeichenkonvertierung stattfinden muss, weil Client und Server die gleiche Codepage verwenden. 

Aber das ist leider falsch! Wahrscheinlich haben Sie für die Anwendung kein altes VT-Terminal, was nur ASCII Zeichen kann sondern einen MS-Windows PC oder einen Linux Rechner mit einer Java Anwendung. In Europa verwendet MS-Windows standardmäßig den Zeichensatz WE8MSWIN1252, das übrigens der umfangreichste ein Byte Zeichensatz ist (also mehr als der für Datenbanken gebräuchliche WE8ISO8859P15) und Java oder auch Anwendungen wie Toad verwenden UTF-8, also einen Multibytes Zeichensatz. Wenn Sie also Oracle Net gesagt haben, dass keine Zeichenkonvertierung stattfinden soll, dann wird dieser Code (also im schlimmsten Fall UTF-8) 1:1 in die Datenbank gespeichert, egal ob das dort gültige Zeichen sind oder nicht. Solange Sie jetzt aber die Zeichen mit der gleichen Anwendung auslesen, mit der Sie sie auch eingegeben haben, merken Sie das nicht einmal. Erst wenn Sie die Anwendung wechseln, z.B. den Toad einsetzen, stellen Sie fest, dass die Zeichen nicht korrekt dargestellt werden. Das sieht dann z.B. so aus:

JA-Blog-090913-3

Jetzt wird Ihnen hoffentlich bewusst geworden sein, wie wichtig es ist, sich mit "Schmutzzeichen" zu beschäftigen. Die Schwierigkeit besteht in der Bereinigung solcher Daten. Ende 2012 habe ich eine Datenbank von US7ASCII auf Unicode migriert, bei der drei unterschiedliche Clients (UTF16, WE8ISO8859P1, WE8MSWIN1252) verwendet worden waren. Der Aufwand war erheblich und wir mussten in der Datenbank mehrfach den Zeichensatz wechseln (was offiziell nicht unterstützt wird) um die Umlaute, Euro-Symbol etc. richtig auslesen zu können.

Letztendlich war die Migration erfolgreich und läuft jetzt mit Unicode. Manchmal schaut der Chef noch mal mit Toad nach, ob die Daten auch "richtig" sind. Mehr dazu finden Sie in meinem Blog "Umlaute unter US7ASCII - geht doch gar nicht! Oder doch?"

3. Zusammenfassung

Eine Unicode Migration ist aufwändig und sollte trotz Tools wie dem Database Migrator for Unicode gut geplant werden. Bevor Sie anfangen, vergewissern Sie sich, dass Sie bitte folgende Punkte beachtet haben:

  • Es gibt ein "Unicode" Projekt mit einem Projektleiter
  • Es gibt ein Budget
  • Das Projekt hat eine Dauer von mindestens 3 Monaten, besser 6 Monate
  • Erwarten Sie Fehler

Wenn Sie diesen Regeln folgen wird die Migration ein Erfolg, wenn nicht, dann laufen Sie Gefahr, dass das eine Katastrophe wird.

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