Update bezüglich Microsoft Excel für Mac und ODBC-Zugriff auf MySQL-Server

Das Folgende ist ein Update für diesen alten Artikel. Ich nutze mittlerweile Microsoft Excel 15 für Mac und El Capitán. Microsoft Query ist kein eigenes Programm mehr, sondern es öffnet sich ein Fenster innerhalb von Excel, das diesen Namen trägt. Dabei handelt es sich im Gegensatz zu früher um ein 32-Bit-x86-Programm. Deshalb muss man nicht mehr mühevoll ein fat binary erzeugen, dafür gibt es neue Probleme. Da ich nirgendwo einen Artikel zu diesem Thema finden konnte, dachte ich mir, dass ich so vielleicht mindestens einer weiteren Person auf dem Planeten helfen kann.

Neben Excel braucht man:

  • die 32-Bit-Version des freien MySQL-ODBC-Connectors (Plattform Mac OS X, Mac OS X 10.7 (x86, 32-bit), DMG Archive, aktuelle Version: 5.3.4)
    NB: man muss den Installer per Rechtsklick öffnen, weil er nicht signiert ist.
  • den ODBC-Manager

Nachdem man beide Pakete installiert hat, muss man zunächst den Connector verschieben oder kopieren. Der Installer installiert ihn nach /usr/local/lib. Wenn man den Connector dort lässt, kann Excel ihn nicht öffnen. Im Systemlog findet man diesen Hinweis:

sandboxd[160] ([45299]): Microsoft Excel(45299) deny file-read-data /usr/local/lib/libmyodbc5w.so

Excel hat über seine Sandbox also keine Leserechte auf das Verzeichnis. Security kann so lästig sein 😉

Dieses Problem kann man im Terminal wie folgt beheben:

$ sudo cp -p /usr/local/lib/libmyodbc* /Library/ODBC/

Wenn man danach den ODBC-Manager (im Ordner Dienstprogramme) startet, sollte man so etwas im Treiber-Tab anlegen:

ODBC-Treiber

Danach muss man für die gewünschte MySQL-Verbindung einen System-DSN anlegen:

DSN anlegen

DSN bearbeiten

Diese Verbindung kann man danach in Excel verwenden:

Datenbankabfrage einfügen

Microsoft Query

Microsoft Query

MySQL-Upgrade wie es sein sollte

Nicht, dass ich im Allgemeinen zu extremer Prokrastination neige, aber im Falle des netten kleinen ToDos „Update der MySQL-Server auf 5.5“ bin ich eindeutig schuldig. Das schob ich nämlich bereits seit Ende 2012 leise vor mir her, da ich den Aufwand für außerordentlich hoch hielt. Zur Ausgangssituation: Aus historischen Gründen hatten wir eine recht heterogene Landschaft im Bereich MySQL-DB-Server, bestehend aus:

* 1 Master-Slave-Cluster, Version 5.1, basierend auf original MySQL-RPMs

* 2 Master-Slave-Clustern, Version 5.1, basierend auf IUS-RPMs

* 1 Master-Slave-Cluster, Version 5.5, basierend auf original MySQL-RPMs

* 1 Master-Master-Cluster, Version 5.1, basierend auf original MySQL-RPMs

Wohlgemerkt: Alle auf RHEL5! Die nun alle auf eine homogene Basis zu stellen (nämlich Version 5.5, basierend auf IUS-RPMs) und dabei sowohl die Daten als auch die Replikation leben zu lassen, schien nur durch komplette Dump-Restores mit zwischenzeitlicher Neuinstallation der Pakete zu funktionieren. Da wir hier über eine Datenmenge von insgesamt etwa einem Terabyte sprechen, rechnete ich mit einer ziemlich großen Downtime.

Ein wenig Recherche nach der optimalen Vorgehensweise brachte jedoch zutage, dass die Jungs und Mädels der IUS Community (http://iuscommunity.org), deren Repositories wir ja auch oft und gerne benutzen, tatsächlich auch an solche wirren Zustände gedacht haben. Genauer gesagt gibt es das hübsche Plugin „replace“ für die Paketverwaltung yum. Es lässt sich – natürlich nach Integration des IUS-Repos – per „yum install yum-plugin-replace“ installieren und eröffnet die Möglichkeit, yum mit der Option „replace-with“ aufzurufen.

So führt das folgende Kommando bspw. dazu, dass ein bisheriger 5.1-Server auf IUS-Basis nahtlos durch einen 5.5-Server ersetzt wird:

yum replace mysql51-libs --replace-with mysql55-libs

Der Wechsel ist aber – und das ist das eigentliche Erstaunliche – auch aus den MySQL-RPMs heraus möglich:

yum replace MySQL-server-community --replace-with mysql55-server

yum bzw. das Plugin löst selbst alle nötigen Abhängigkeiten auf. Ggf. beschwert es sich, dass die Herkunft einiger beteiligter Pakete nicht ermittelt werden konnte, dies kann man aber problemlos ignorieren.

Letztendlich war es mir so möglich, das gefürchtete Upgrade für alle Server in einer Stunde durchzuführen, ohne dass ich bislang ein Problem feststellen konnte. Einige Hinweise gilt es aber noch zu beachten:

  • Laut MySQL sollte immer der Slave zuerst aktualisiert werden.
  • Nach dem Upgrade von Slave und Master muss auf dem Master das Kommando „mysql_upgrade“ ausgeführt werden, um fehlende MySQL-Tabellen zu ergänzen. Zudem werden bei der Gelegenheit alle Tabellen geprüft und ggf. repariert.
  • Beim Wechsel von MySQL 5.5 aus MySQL-RPMs auf MySQL 5.5 aus IUS-RPMs musste ich zuvor manuell das Paket „MySQL-shared-compat“ entfernen. Das konnte das Plugin aus irgendwelchen Gründen nicht lösen.
  • Bei Statement-basierter Replikation wirft MySQL 5.5 im Gegensatz zu 5.1 Warnungen, wenn Anweisungen bspw. nicht-deterministische Ergebnisse liefern. Diese Warnungen waren nicht zu unterdrücken (jedenfalls habe ich den Schalter nicht gefunden), obwohl wir uns der Tatsache bewusst waren und die entsprechende Datenbank ohnehin von der Replikation ausgenommen hatten. Ein somit ohnehin fälliger Wechsel zum „Mixed“-Format war also unvermeidlich (Schalter „binlog-format = MIXED“)
  • In MySQL 5.5 fallen einige Konfigurationsoptionen weg bzw. sollten durch ihre Nachfolger ersetzt werden. Die Ersetzung kann bereits vor dem Upgrade in der my.cnf durchgeführt werden. Aufgefallen sind bei mir:
    • skip-locking
    • log-err (ersetzt durch log-error)
    • key_buffer (ersetzt durch key_buffer_size)
    • thread_cache (ersetzt durch thread_cache_size)

MySQL-Speicherverbrauch

Wer sich ein wenig mit MySQL beschäftigt hat, weiß, dass es nicht nur in den Features, sondern auch im Handling einige Unterschiede zwischen den DB-Engines MyISAM und InnoDB gibt.
Die Transaktionssicherheit von InnoDB erkauft man sich u.a. durch eine geringere Transparenz, wo welche Daten liegen und auch wie viel Speicherplatz von den einzelnen Tabellen und Datenbanken belegt werden, da die InnoDB im Gegensatz zur MyISAM ihre Daten nicht in separaten Dateien ablegt, sondern alle Daten aller Datenbanken in nur einer Datei vereint.. Hat man viele Datenbanken mit vielen Tabellen, erschwert dies die Fehlersuche und Optimierung ungemein.

Ich habe hier ein paar MySQL-Queries zusammen gestellt, welche die gewünschten Informationen aus den Tabellen der MySQL-eigenen Datenbank „information_schema“ lesen.

Wer sich ein wenig mit MySQL beschäftigt hat, weiß, dass es nicht nur in den Features, sondern auch im Handling einige Unterschiede zwischen den DB-Engines MyISAM und InnoDB gibt.
Die Transaktionssicherheit von InnoDB erkauft man sich u.a. durch eine geringere Transparenz, wo welche Daten liegen und auch wie viel Speicherplatz von den einzelnen Tabellen und Datenbanken belegt werden, da die InnoDB im Gegensatz zur MyISAM ihre Daten nicht in separaten Dateien ablegt, sondern alle Daten aller Datenbanken in nur einer Datei vereint.. Hat man viele Datenbanken mit vielen Tabellen, erschwert dies die Fehlersuche und Optimierung ungemein.

PHPMyAdmin zeigt zwar die Größe der Tabellen an, aber man muss dazu jede einzelne Datenbank anklicken und verliert so den Überblick.

Ich habe hier ein paar MySQL-Queries zusammen gestellt, welche die gewünschten Informationen aus den Tabellen der MySQL-eigenen Datenbank „information_schema“ lesen.

Voraussetzung für alle folgenden Queries ist eine SQL-Verbindung zum Server mit einem Account, der für das Lesen der Informationen aus der Datenbank „information_schema“ berechtigt ist – also z.B. „root“;

Warnung: Diese Anweisungen sammeln Daten über sämtliche Inhalte eines Servers, bei großen Datenmengen und langsamen Servern können diese eine Laufzeit von mehreren Minuten haben und den Betrieb des Servers stark beeinflussen!

Gesamt-Verbrauch aller DBs

Möchte man die Größe aller Datenbanken auf einem Datenbank-Server erfahren, so kann dazu der folgende SQL-Befehl verwendet werden:
SELECT concat( round( sum( data_length + index_length ) / ( 1024 *1024 ) , 2 ) , 'M' ) size
FROM information_schema.TABLES ;

Hierbei wird die Speicherplatzbelegung, die in Bytes vorliegt gleich in MB umgerechnet, für Fälle, in denen das nicht sinnvoll ist, lässt man natürlich die Funktionen round und concat weg und teilt auch nicht durch ( 1024*1024 ).
Diese Abfrage addiert den Speicherplatz-Verbrauch der Daten und ihrer Indices, wer diese Größen getrennt braucht, kann obige Abfrage leicht modifizieren.

Diese Abfrage lässt sich natürlich weiter verfeinern. Da man die Speicherplatzbelegung der MyISAM-Tabellen leicht anhand der Größen der einzelnen Dateien ablesen kann, gehen wir ab hier nur noch auf die InnoDB ein.

Gesamt-Verbrauch aller InnoDB-Tabellen

Die Daten der InnoDB-Engine liegen, wie gesagt, in nur einer Datei. Häufig ist diese Datei mit der Option „autoextend“ konfiguriert, so dass die Datei automatisch vergrößert wird, sobald neue Daten in die Datenbank geschrieben werden. Jedoch schrumpft sie nicht, wenn Daten gelöscht werden. Der freigewordene Speicherplatz innerhalb der Datei, kann wieder von Daten in der InnoDB belegt werden, es dauert also, bis die InnoDB-Datei wieder voll ist, und sie mittels autoextend vergrößert werden muss, aber auf der Festplatte des Servers wird dieser Speicherplatz nie wieder freigegeben. So kann es sein, dass die Datei auf der Festplatte deutlich größer ist, als die Nutzdaten darin.
Um zu erfahren, wie viele Nutzdaten sich also derzeit wirklich in der InnoDB befinden, ist folgende Abfrage nützlich:
SELECT concat( round( sum( data_length + index_length ) / ( 1024 *1024 ) , 2 ) , 'M' ) size
FROM information_schema.TABLES
WHERE ENGINE='InnoDB' ;

InnoDB-Speicherverbrauch pro Datenbank

Um zu erfahren, in welcher Datenbank der Speicher verbraucht wird, kann man sich hiermit leicht einen Überblick verschaffen:
SELECT table_schema 'database', concat( round( sum( data_length + index_length ) / ( 1024 *1024 ) , 2 ) , 'M' ) size
FROM information_schema.TABLES
WHERE ENGINE='InnoDB'
GROUP BY table_schema
ORDER BY sum( data_length + index_length );

In diesem Fall wird das Resultat auch noch nach der Größe sortiert.

Hinweis: Nicht vergessen, in diesen Größen-Angaben werden alle Daten, die nicht mit der Engine InnoDB verwaltet werden ignoriert. Will man alle Daten sehen muss die Anweisung WHERE ENGINE='InnoDB' weggelassen werden.

InnoDB-Speicherverbrauch pro Tabelle

Um zu erfahren, in welcher Tabelle einer bestimmten Datenbank der Speicher verbraucht wird, kann hiermit die Datenbank näher inspizieren, dabei muss in der Abfrage natürlich der Name der betreffenden Datenbank anstelle des Platzhalters [DATABASE_NAME] eingetragen werden:
SELECT table_name 'table', concat(round((data_length+index_length)/(1024*1024),2),'M') size
FROM information_schema.TABLES
WHERE ENGINE='InnoDB'
AND table_schema = '[DATABASE_NAME]'
ORDER BY ( data_length + index_length );

Große InnoDB-Tabellen auf einem Server finden

Möchte man einen ganzen Server nach Tabellen einer bestimmten (Mindest-)Größe durchsuchen, ohne den Umweg über die Größe der Datenbanken zu nehmen, kann man dies auch direkt in einer Anweisung formulieren. Da viele Tabellen sehr klein sind, ist es selten sinnvoll sich die Größe aller Tabellen eines Servers anzuzeigen, daher dient die letzte hier vorgestellte Abfrage dazu, alle Tabellen eines Servers anzuzeigen, die in der InnoDB mindestens 100MB belegen. Die Angabe der Mindestgröße geschieht hierbei in Byte, daher steht in der WHERE-Anweisung des SQL die Zahl 104857600 (=100*1024*1024):
SELECT table_schema 'database', table_name 'table', concat(round((data_length+index_length)/(1024*1024),2),'M') size
FROM information_schema.TABLES
WHERE ENGINE='InnoDB'
AND data_length + index_length >104857600
ORDER BY ( data_length + index_length );

Mit dem Excel aus Office 2008 mit einem Intel-Mac auf MySQL zugreifen

Heute kam mir zum ersten Mal eine sinnvolle Anwendung für eine ODBC-Anbindung einer MySQL-Datenbank an Microsoft Excel in den Sinn. Zum Glück war meine erste Aktion nach der Idee eine Google-Suche. Dadurch habe ich einen Foreneintrag gefunden, der mir eine Menge Arbeit erspart hat.
Der Hintergrund ist, dass es eine Reihe von Problemen gibt:

  • Obwohl Office 2008 Macs mit Intel-Prozessoren nativ unterstützt, ist das Hilfsprogramm Microsoft Query seit 2002 unverändert und hat nur PowerPC-Code.
  • Der freie ODBC-Connector von MySQL wird nicht als „fat binary“ angeboten, sondern nur wahlweise als ppc- oder x86-Code.
  • Excel 2008 hat eine hartkodierte Liste von unterstützten ODBC-Konnektoren, die nicht den MySQL-Connector enthält.

Wenn man eine schnelle und einfache Lösung für alle genannten Problem will, kann man einen der offiziell von Microsoft unterstützten Konnektoren kaufen. Getestet habe ich nur den von Actual Technologies (siehe unten).

Da es einen freien Konnektor gibt, sehe ich aber nicht ein, warum ich einen kaufen soll. Hier sind die Schritte, um den freien MySQL-Connector benutzen zu können:

  • bei MySQL die Konnektoren für PowerPC und x86 separat runterladen (im „package format“)
  • Achtung: in gemounteter Form heißen beide gleich, so dass man die Architektur nicht mehr erkennen kann. Deshalb sollten die Images jeweils manuell nach Bedarf gemountet werden.
  • Das Image für x86 mounten (Doppelklick) und den Installer für x86 ausführen
  • im Terminal wie folgt aus den Shared Libraries beider Architekturen sog. „fat binaries“ bauen:
  • mkdir ODBC_ppc ODBC_x86 ODBC_fat
  • cd ODBC_x86
  • pax -zrf /Volumes/MySQL Connector ODBC 5.1/MySQL Connector ODBC 5.1.pkg/Contents/Archive.pax.gz
  • x86-Image auswerfen, ppc-Image mounten
  • cd ../ODBC_ppc
  • pax -zrf /Volumes/MySQL Connector ODBC 5.1/MySQL Connector ODBC 5.1.pkg/Contents/Archive.pax.gz
  • cd ..
  • lipo ./ODBC_ppc/usr/local/lib/libmyodbc3S-5.1.5.so ./ODBC_x86/usr/local/lib/libmyodbc3S-5.1.5.so -output ODBC_fat/libmyodbc3S-5.1.5.so -create
  • lipo ./ODBC_ppc/usr/local/lib/libmyodbc3S.so ./ODBC_x86/usr/local/lib/libmyodbc3S.so -output ODBC_fat/libmyodbc3S.so -create
  • lipo ./ODBC_ppc/usr/local/lib/libmyodbc5.so ./ODBC_x86/usr/local/lib/libmyodbc5.so -output ODBC_fat/libmyodbc5.so -create
  • sudo cp ODBC_fat/* /usr/local/lib/
  • An dieser Stelle hat man einen „fetten“ MySQL-Connector, den man mit Dienstprogramme->ODBC-Administrator konfigurieren kann. Ich habe einen Benutzer-DSN hinzugefügt.
  • Da Excel sich noch weigert, wenn man Daten->Externe Daten->Neue Abfrage erstellen auswählt, muss man die Demo-Version von Actual Technologies installieren.
  • Jetzt startet Microsoft Query, wenn man es aus Excel aufruft, und man kann auch den MySQL-Connector benutzen


Flattr this