Wenn MySQL stirbt…

Es begann harmlos: In meiner Friendica-Instanz wurde ein Bild nicht geladen. Als ich mir das genauer ansah, stellte sich heraus, dass das Bild aus der Datenbank gezogen wurde und dabei ein Mysql Server gone produzierte. Im Log von MySQL tauchten dazu so hässliche Meldungen wie diese auf:

[...]
Some pointers may be invalid and cause the dump to abort.
Query (7feb68c6ba50): is an invalid pointer
Connection ID (thread ID): 6
Status: NOT_KILLED
[...]

Bei dem NOT_KILLED blieb es nicht immer, nach ein paar weiteren Versuchen war der MySQL-Server tatsächlich tot … liess sich aber noch neu starten. Die naheliegende Rettungsmöglichkeit Backup einspielen scheiterte daran, dass seit einiger Zeit das Backup via mysqldump abgebrochen war und zwar in der Friendica-Tabelle conversation.

Also musste ich reparieren.

Um nicht noch mehr Datenverlust zu riskieren, habe ich erst mal das Datenverzeichnis kopiert:

cp -rfv /var/lib/mysql /var/lib/mysql$(date +%s)

Danach veruschte ich zu retten, was zu retten ist. Im Error-Log von MySQL wurde ich auf http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html verwiesen … das funktionierte nur leider nicht.

Nächster Versuch: da ich durch das Backup etwa wusste, ab welchem Datensatz etwas kauptt war, versuchte einfach ab dort ein paar Datensätze zu löschen. Ergebnis: der MySQL Server fiel komplett aus und lissß sich nicht mehr starten. In dem Moment war ich wirklich froh vorher das Datenverzeichnis in Sicherheit gebracht zu haben.

Die Lösung war dann recht rüde: ich habe conversation per TRUNCATE geleert und danach noch photo (gleicher Fehler).Jetzt liess sich endlich ein Dump ziehen. Noch schnell die Datenbank gelöscht und via Dump neu aufgesetzt. Alles lief danach wieder normal … magischerweise sogar Friendica, jedenfalls weitestgehend.

Was habe ich daraus gelernt?

  1. Mache von jeder Datenbank auf deinem Server ein einzelnes Backup (--all-databases ist eine schlechte Idee)
  2. Kontrolliere den Rückgabestatus von mysqldump

Oder als Skript (vereinfachte Kurzfassung):

doBackup () {
   mysqldump -u $1 -p$2 $3 > $3.dump
   if [[ $? -eq 0 ]]; then
     gzip $3.dump
   else
     echo >&2 "backup of $3 failed"
     exit 1
   fi
 }

doBackup "USER" "PASSWORD" "DB
 […]

TEMPer mit ID 413d:2107

Ich hatte eigentlich etwas ganz einfaches vor: an meinen RasPi einen Temperatursensor anschliessen und mal längere Zeit das Auf und Ab der Temperatur in unserer Wohnung beobachten. Passend erschien mir der TEMPer: er ist preiswert und es gibt Unterstützung für Linux (allerdings nicht vom Hersteller, der liefert nur eine recht grottige Windows-Software mit).

Als das Ding ein paar Tage nach der Bestellung aus China eintrudelte, schaute ich mir erst mal an, was ich da habe.

lsusb lieferte

[...]
Bus 001 Device 005: ID 413d:2107  
[...]

Das war schon mal eine USB-ID, die für dieses Ding eher ungewöhnlich war. Das versprach nichts Gutes.

Die grundlegenden Treiber finden sich auf https://github.com/signal11/hidapi und müssen selbst kompiliert werden. Das ist zwar dort noch mal alles gut beschrieben, aber hier noch mal meine Zusammenfassung:

Erst das Repository klonen …

git clone git://github.com/signal11/hidapi.git

… dann die Voraussetzungen für das spätere Kompilieren installieren …

sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev autotools-dev autoconf automake libtool

… und die Build-Schritte durchführen

./bootstrap
./configure
make
sudo make install  

An dieser Stelle ist man leider noch nicht fertig, es braucht für die Temperatursensoren noch ein zweites Projekt, das sich auf https://github.com/edorfaus/TEMPered befinden

Und wieder das Repository klonen (parallel zum hidapi-Projekt; das vereinfacht die folgenden Schritte) …

git clone https://github.com/edorfaus/TEMPered.git

… dann die Voraussetzungen für das spätere Kompilieren installieren …

sudo apt install cmake

… und zum Schluss die Build-Schritte durchführen

cmake .
make

In utils liegt jetzt hid-query, mit dem man die verbundenen Devices auflisten kann:

hid-query -e
/dev/hidraw0 : 413d:2107 interface 0 : (null) (null)
/dev/hidraw1 : 413d:2107 interface 1 : (null) (null)

Um herauszufinden, wie man an die Werte kommt, sendet man nacheinander an die beiden Devices (hier hidraw0 und hidraw1) eine entsprechende Aufforderung

sudo hid-query /dev/hidraw0 0x01 0x80 0x33 0x01 0x00 0x00 0x00 0x00

In meinem Fall „hing“ der Request bei dem einen Device und gab für das andere die folgende Antwort:

Writing data (9 bytes):
         00 01 80 33   01 00 00 00   00
​
Response from device (8 bytes):
         80 80 0b ab   4e 20 00 00

Leider kennt tempered diese Version des Sticks noch nicht. Da ich zu faul war mich in den C-Code einzuarbeiten, habe ich aus den diversen Postings zu den Issues auf github mir den Code zu einem kleinen Bash-Skript herausgeholt, das zusammen Human_Interface_Device hid-query die aktuelle Temperatur ausgibt. Dazu muß ggf. erst noch bc installiert werden:

sudo apt install bc

Dann braucht es nur noch ein kleines Skript …

#!/bin/bash
OFFSET=0.0
OUTLINE=`sudo hid-query /dev/hidraw1 0x01 0x80 0x33 0x01 0x00 0x00 0x00 0x00|grep -A1 ^Response|tail -1`
OUTNUM=`echo $OUTLINE|sed -e 's/^[^0-9a-f]*[0-9a-f][0-9a-f] [0-9a-f][0-9a-f] \([0-9a-f][0-9a-f]\) \([0-9a-f][0-9a-f]\) .*$/0x\1\2/'`
HEX4=${OUTNUM:2:4}
DVAL=$(( 16#$HEX4 ))
bc <<< "scale=2; $DVAL/100 - $OFFSET"

… und man hat die aktuelle Temperatur … fast. Denn zunächst muss man das Ergebnis noch mit einem guten Thermometer vergleichen, dann der Stick hat ein konstantes Offset zur realen Temperatur. Sobald man die Differenz kennt sollte die 0.0 im Skript angepasst werden.

Noch ein Hinweis zum Schluss: Der Stick sollte nicht direkt an einem Rechner betrieben werden, sondern per Verlängerungskabel etwas Abstand haben. Sonst beheizt der Rechner den Stick und die Messungen sind sinnlos.