Foreign Keys in MySQL temporär deaktivieren

Eines der besten Funktionen die mit InnoDB Einzug bei MySQL gehalten haben, ist die Unterstützung von Fremd Schlüsseln (Foreign Keys). Doch diese tolle Funktion kann schnell nervig sein, wenn zum Beispiel Tabellen mit Fremdschlüsseln gelöscht oder geleert werden sollen. Auch das Einspielen von mehreren Datenzeilen zum Testen kann somit schnell nerven, wenn die Beziehungen nicht erfüllt sind.

Mit einem einfachen SQL Befehl kann man jedoch kurzzeitig die Fremdschlüsselüberprüfung ausschalten.

mysql> SET FOREIGN_KEY_CHECKS = 0;

Aktivieren lässt sich die Überprüfung mit

mysql> SET FOREIGN_KEY_CHECKS = 1;

Doch Vorsicht! Die Fremdschlüsselüberprüfung lässt sich nur wieder einschalten, wenn auch alle Einträge konform sind.

Benutzer mit Rechten für mysqldump ausstatten

MySQL Backupscripte sind ein potentielles Sicherheitsrisiko, wenn zum Sichern der root Benutzer verwendet wird. Denn meist steht das Passwort direkt im Script oder ist in der my.cnf abgelegt. Ein potenzieller Angreifer der lesend auf das System gelangt, hat dadurch leichtes Spiel an die Passwörter zu kommen. Deshalb empfiehlt es sich Backups mit einem separaten Benutzer anzulegen, der nur die nötigsten Rechte hat. Ich gehe meist wie folgt vor:

Benutzer angelegen

CREATE USER 'backupnutzer'@'localhost' IDENTIFIED BY 'geheim';

Berechtigungen setzen (Wer keine Trigger oder Views benutzt kann SHOW VIEW bzw. TRIGGER auch weg lassen.)

GRANT SELECT, FILE, LOCK TABLES, SHOW VIEW, TRIGGER ON *.* TO 'backupnutzer'@'localhost';

Hinweis! Diese Query vergibt globale Rechte. Will man nur auf eine bestimmte Datenbank sichern sollte der Befehl so aussehen.

GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER ON datenbank.* TO 'backupnutzer'@'localhost';

Rechte neu einlesen

FLUSH PRIVILEGES;

Fertig. Nun kann der Benutzer backupnutzer mit dem Passwort geheim in den Scripten verwendet werden. Ein potentieller Angreifer würde zwar trotzdem noch auf die Datenbank gelangen, könnte aber deutlich weniger Schaden anrichten.

MSSQL Datetime in MySQL Datetime konvertieren

In einem aktuellen Projekt erhalte ich Exporte aus einer MSSQL Datenbank. Diese wiederum sollen in eine MySQL Datenbank eingespielt werden. Mein Problem: Felder des Typs Datetime werden im Format 24.06.2013 07:26:20 geliefert, benötigt wird aber 2013-06-24 07:26:20.

Der MySQL CAST liefert leider keine gültigen Werte.

SELECT CAST( '24.06.2013 07:26:20' AS DATETIME);

Mit einem kleinen Umweg bekommt man es aber doch formatiert.

SELECT DATE_FORMAT( STR_TO_DATE('24.06.2013 07:26:20', '%d.%m.%Y %H:%i:%s'), '%Y-%m-%d %H:%i:%s' );

MySQL Server mit mytop überwachen

mytopVielen Linuxanwendern sind Befehle wie top oder htop ein gängiger Begriff. Auch für den Datenbankserver MySQL gibt ein top-ähnliches Überwachungstool – mytop. Dieses kleine Programm bietet dem Admin einen schnellen Überblick der derzeitigen Serverauslastung und Nutzung.

mytop findet sich in den Ubuntu Paketquellen und lässt sich wie folgt installieren.

$ sudo apt-get install mytop

Nach der Installation könnte ein Beispielaufruf so aussehen:

mytop -u BENUTZER -p PASSWORT -h HOST-d DATENBANK

Alternativ zu diesem Aufruf kann man sich auch die Parameter sparen und diese in der Konfigurationsdatei ~/.mytop ablegen.

user=BENUTZER
pass=PASSWORT
host=HOST
db=DATENBANK
delay=5
port=3306
batchmode=0
header=1
color=1
idle=1

Achtung! Das Speichern von Passwörtern im Klartext kann gefährlich sein! Man sollte sicher gehen das kein Dritter Zugriff auf die Datei ~/.mytop erlangen kann! Verwendung also auf eigene Gefahr!

UDATE statt INSERT wenn doppelter Eintrag

Nehmen wir folgenden Fall an: Ich habe eine Tabelle mit verschiedenen Werten.

CREATE TABLE `xyz` (  
    `a` VARCHAR(50) NOT NULL,  
    `b` INT(10) NOT NULL DEFAULT '0',  
    `c` DATETIME NOT NULL
);

Bisher wurden die Werte wild hinzugefügt oder geändert.

INSERT INTO `xyz` (`a` ,`b` ,`c`) VALUES ('Testeintrag', '123', NOW());
oder
UPDATE `xyz` SET `a`='Testeintrag',`c`=NOW() WHERE b='123';

Jetzt aber möchte ich dieser Tabelle etwas hinzufügen – aber nur dann – wenn der Wert in Spalte b nicht existiert. Andernfalls muss der Eintrag geändert werden. Dieses Konstrukt über die Applikationslogik(en) abzubilden, wäre in meinem Fall aber recht aufwändig gewesen. Deshalb musste eine andere Lösung her.

MySQL bietet in diesem Fall eine einfache Lösung an INSERT … ON DUPLICATE KEY UPDATE. Hierzu muss die entscheidende Spalte b als UNIQUE definiert werden (Hinweis: Doppelte Eintrage in MySQL Tabelle finden) und die Query in der Applikation wie folgt angepasst werden.

INSERT INTO `xyz` (`a` ,`b` ,`c`) VALUES ('Testeintrag', '123', NOW())
ON DUPLICATE KEY UPDATE `a`='Testeintrag',`c`=NOW();

Wenn jetzt der Wert der Spalte b bereits in der Tabelle enthalten ist, wird diese Spalte einfach aktualisiert.

Weitere Informationen zum Thema:
http://dev.mysql.com/doc/refman/5.1/de/insert-on-duplicate.html