Mit R Daten aus MySQL-Datenbank von entferntem Server holen (Linux)

R (R-Project) kann bekanntlich mit sämtlichen lokalen Daten gefüttert werden. Um Daten aus einer MySQL-Datenbank auszulesen, brauchen wir das R-Paket RMySQL, welches sich des Backends DBI (DataBase Interface) bedient. Damit die Installation des Pakets unter Ubuntu Linux glatt durchläuft, installieren wir vorab (außerhalb von R!) das Paket libmysqlclient-dev via

sudo apt-get install libmysqlclient-dev

(evlt. benötigt man noch das META-Paket build-essential, was aber bei der Installation des Paket in R auffallen wird. Wobei man die build-essential(s) immer mal gut gebrauchen kann. ;-) )

In R selbst installiert man Pakete bekanntlich mit

install.packages("mypkg")

Tut man dies ohne Rootrechte, landen die zusätzlichen Pakete im eigenen Homeverzeichnis. Deshalb starten wir R ausnahmsweise mit Rootrechten:

sudo R

In R starten wir die Installation mit

install.packages("RMySQL")

Woraufhin R eine Liste mit Mirror-Servern präsentieren wird. Am besten einen der nächstgelegenen auswählen. Allerdings haben nicht alles Mirrors alle Packages parat. Nichtsdestotrotz erstmal warten. Von der Auswahl bis zum Beginn der Installation kann einige Zeit vergehen. Die Installation sollte nun ohne Meckereien durchlaufen. Jetzt kann man R verlassen, denn wir wollen ja nicht mit Rootrechten weiter arbeiten. Stattdessen starten wir als Nutzer, der wir sind.

Verbindungsaufbau zum MySQL-Server

Entgegen anderer Meinungen, die da im Netz (noch) kursieren kann R sich nicht nur über den lokalen MySQL-Socket in die Datenbank hängen, sonder auch über einen entfernten (remote) MySQL-Server, wenn dieser dies zulässt(!). Der Code in R würde folgendermaßen aussehen:

library(RMySQL) # läd das Paket und aktiviert es
drv < - dbDriver("MySQL") # Typ der Datenbank
con <- dbConnect(drv, user="hans", password="qwertz", dbname="datenbank", host="mysql.domain.com")

Damit sollte die Verbindung stehen. Da aber die meisten MySQL-Server standardmäßig aus Sicherheitsgründen keine externen Verbindungen zulassen, müsste man diese ersten in der Datei my.cnf erlauben. Das kann nicht dadurch ersetzt werden, dass man einzelnen Nutzern erlaubt über das Netzwerk Verbindungen aufzubauen! Und zwar muss in der my.cnf die Zeile mit skip-networking auskommentiert werden. Da diese Daten unverschlüsselt durch den Äther rauschen, sollte man über eine sichere Verbindungen nachdenken, die den Server auch nicht dazu zwingt “die Hosen runter zu lassen”.

Verbindung: Aber sicher! Verschlüsselter Tunnel mittels SSH

Mit SSH kann man so gut wie alles machen. Eben auch Netzwerkverbindungen tunneln. In unserem Fall wollen wir auf einem lokalen Port einen entfernten MySQL-Server zur Verfügung stellen. Damit ist die Verbindung verschlüsselt, und auf dem entfernten MySQL-Server muss kein anderer Port offen sein als die 22 für SSH. Folgender Befehl etabliert den Tunnel:

ssh -L 3306:localhost:3306 mysql.meinserver.com

Steht der Tunnel, muss R auch nicht mehr direkt mit dem MySQL-Server sprechen, sondern wendet sich einfach an den lokalen Port, der ja weitergeleitet wird:

con < - dbConnect(drv, user="hans", password="qwertz", dbname="datenbank", host="127.0.0.1")

Ich habe absichtlich die 127.0.0.1 genommen, um zu vermeiden, dass R auf die Idee kommt, den lokalen MySQL-Socket zu nutzen, sonder wirklich das Netzwerk.

Daten auslesen

Sind wir erstmal “drin”, kann bequem mit der Datenbank gearbeitet werden. So zeigt z.B.

dbListTables(con)

alle Tabellen in der aktuellen Datenbank an. Mit

dbReadTable(con, "Tabelle")

werden alle Variablen und deren Werte der Tabelle mit dem Namen “Tabelle” ausgegeben. Man kann aber auch SELECTs ausführen:

dbGetQuery(con, paste(”SELECT width FROM Tabelle “,”WHERE vorname=’georg’ “))

Praktischer Weise sollte man die Abfragen gleich in Variablen stecken. Nach getaner Arbeit sollte man die Verbindung (Connection) zum MySQL-Server auch wieder sauber schließen:

dbDisconnect(con)

That’s it.

Leave a Reply