Wichtige Info

Die Inhalte, die du hier siehst stelle ich dir ohne Werbeanzeigen und ohne Tracking deiner Daten zur Verfügung. Trotzdem muss ich die Server bezahlen sowie Zeit in Recherche, Umsetzung sowie Mail Support stecken.
Um dies leisten zu können, verlinke ich in einigen Artikeln auf die Plattform Amazon. Alle diese Links nennen sich Afiliate Links. Wenn du dir mit diesem Link etwas kaufst, dann erhalte ich eine kleine Provision. Dies ändert jedoch NICHT den Preis, den du bezahlst!
Falls du mich also unterstützen möchtest, kannst du auf den Link zum Produkt klicken und hilfst mir dabei, dieses Hobby weiter zu betreiben.
Da ich Keine Werbung schalte und keine Spenden sammle, ist dies die einzige Möglichkeit, meine Systeme und mich zu finanzieren. Ich hoffe du kannst das verstehen :)



Homeassistant - Datenbank auf einen eigenen Server auslagern


Einleitung:

Ich baue seid geraumer Zeit mein Smart Home auf und mit einer der Hauptgründe für eben dieses, sind für mich ganz simpel gesagt: Statistiken. Diagramme aller Art, Analysen und Auswertungen über mein Leben erstellen, ist für mich ein sehr interessanter Bereich, um mich und meine vernderung grafisch darstellen zu können. Kostenminimierung und Komfort stehen aber selbstverständlich auch auf meiner Agenda. Um das alles umsetzen zu können bzw. prüfen zu können (im Fall von Kostenminimierung), benötige ich jedoch Daten. Diese Daten werden im Normalfall in einer SQLite3 Datenbank auf dem Homeassistant Server selbst gespeichert.
Nun habe ich schon öfter gelesen,d ass genau diese Datenbank gerne mal Fehler hat und dann nur durch ein Backup wiederhgergestellt werden kann. In meinem Fall werden alle 24h Backups erstellt, was bei mir im worstcase 23h Datenverlust bedeutet. Grundsätzlich für meinen Rahmen als Privatperson nicht schlimm, aber trotzdem ist das für mich zuviel.
Dementsprechend möchte ich meine Datenbank gerne auslagern, das hat auch noch weitere Vorteile, denn auch wenn mein Homeassistant einmal nicht mehr funktionieren sollte, sind meine Daten immer da. Ich kann ohne Probleme die Homeasisstant VM löschen und neu aufsetzen, die Daten bleiben durch einen externen DB Server erhalten. Weiterhin können dadurch auch Fremdprogramme auf diese Daten zugreifen und analysieren.
Zuletzt kann ich auch ein hausgemachtes Problem, durch die Auslagerung lösen, nämlich Speichermangel. Meine Homeassistant Instanz hat 32 GB Speicher zu Anfang zugewiesen bekommen und da ich danach neue Maschinen erstellt habe, ist eine Vergrößerung nur mit Aufwand möglich, wenn ich den gesamten Speicherbereich verschiebe. Ohne meine Datenbank spare ich (nach drei Monaten Laufzeit) bereits 4GB ein. Daher zeige ich im folgenden, wie die SQLite3 Datenbank auf einen Maria DB Server unter Debian migriert werden kann.

Homeassistant Datenbank exportieren

Zuerst muss die Homeasistant Datenbank exportiert werden. Dafür können zahlreiche Methoden verwendet werden, unter anderem kann die Datenbank einfach aus dem GUI mit einem Addon heruntergeladen werden, jedoch wollte ich die Datenbank exportieren, währenmd Homeassistant nicht läuft, daher habe ich den Server einfach heruntergefahren und mein Image (im qcow2 Format) mit einer VM gemounted und die Datei auf ein internes SMB Laufwerk kopiert um damit weiterarbeiten zu können. Je nach Installationstyp, kannst du den Homeassistant Dienst auch einfach stoppen und ganz normal auf deinem Filesystem navigieren.
Ich nutze die Homeassistant OS Version unter Unraid als VM und hatte daher einfach die VM gestoppt und wie in diesem Beitrag gezeigt, die Datei exportiert.

Datenbank Server vorbereiten

In meinem Fall nutze ich als Datenbank Server einen “externen” Server, welcher ebenfalls virtualisiert auf meinem Unraid läuft (mit “extern” meine ich, dass nicht die selbe VM wie die HASS Maschine verwendet wird).

Ich gehe hier davon aus, dass bereits ein MariaDB Server (oder Ähnliches) installiert wurde und eine Datenbank mit passendem User erstellt wurde, wie sowas gemacht wird, ist breit im Internet beschrieben, runtergebrochen auf einen Satz wäre es aber nicht viel mehr als “apt install mariadb-server”, die Anpassung des Netzwerks und dann im MariaDB CLI ->

create database homeassistant;
create user 'homeassistant'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES on homeassistant.* to homeassistant@'%';

Im Normalfall ist die MariaDB Installation lokal gebunden und kann nicht von aussen erreicht werden. Das möchte ich bei mir ändern, da da mein Homeassistant später über das Netzwerk auf diesen zugreift.

Dafür passe ich die MariaDB Server config an (Datei: /etc/mysql/mariadb.conf.d/50-server.cnf)

Hier muss der Abschnitt “[mysqld]” angepasst werden, da wir dem Daemon Dienst sagen wollen, dass er nicht nur auf localhost sondern auch auf die IP Adresse reagieren soll.
Die angepasste Konfigurationszeile sieht dann bei mir wie folgt aus:

[mysqld]
...
bind-address            = 192.168.2.16

Danach starte ich den Dienst durch den Befehl “sudo service mariadb restart” neu.

Übertragen der Daten von Homeassistant

WARNUNG: Wie öfter in verschiedenen Foren zu lesen ist, gibt es derzeit Probleme mit dem Energy Dashboard, wenn eine andere Datenbank verwendet wird.
In meinem Fall werden die Strompreise derzeit nicht mehr korrekt kalkuliert, ansonsten funktioniert aber alles, weshalb ich weiter auf diese Lösung setzen werde und nebenbei schaue, wo das Problem liegt. Derzeit ist eine Vermutung vom Forum, dass die Daten des Energydashboards an einer weiteren Stelle gespeichert, aber nicht korrekt migriert werden. Falls euch das Risiko zu hoch ist, solltet ihr hier abbrechen! – oder die Daten nicht übertragen, bei Neustart tritt das Problem wohl nicht auf.

Wir nutzen nun die Datenbank, welche wir von Homeassistant exportiert haben.

Zur übertragung der Daten nutze ich ein Python Script, welches bei mir besser, als das GitHub Projekt funktioniert hat. Zur Installation kann einfach dieses Python Projekt verwendet werden. Installierbar mit

pip install sqlite3-to-mysql

nach der Installation kann auch schon die Übertragung stattfinden.

sqlite3mysql -f <<SQLite Datenbank>> -d <<Database>> -u <<User>> -h <<Host>> -p -t -i DEFAULT

Ich musste meiner VM insgesamt 8 GB RAM für die Übertragung zuweisen, da das Script ansonsten Out of Memory ging, das sollte ggf. beachtet werden, falls ihr größere Datenbanken habt. Meine war ca. 2,2GB Groß).

Nach der Übertragung müssen die Table angepasst werden, dafür habe ich von diesem Post
das vorgehen kopiert. – KEIN COPY PASTE SCRIPT! – LESEN!!!!! – ansonsten zerschießt ihr euch die Daten!

update events set event_data = REPLACE(event_data, '`', '"'); 
update states set attributes = REPLACE(attributes, '`', '"');
update state_attributes set shared_attrs = REPLACE(shared_attrs, '`', '"');
update event_data set shared_data = REPLACE(shared_data, '`', '"');

# Remove Foreign Key Constraints

ALTER TABLE `states` DROP FOREIGN KEY `states_ibfk_1`;
ALTER TABLE `states` DROP FOREIGN KEY `states_ibfk_2`;
ALTER TABLE `states` DROP FOREIGN KEY `states_ibfk_3`;
ALTER TABLE `statistics_short_term` DROP FOREIGN KEY `statistics_short_term_ibfk_1`;
ALTER TABLE `statistics` DROP FOREIGN KEY `statistics_ibfk_1`;
ALTER TABLE `events` DROP FOREIGN KEY `events_ibfk_1`;


# THIS IS NOT A SCRIPT TO COPY AND PASTE, PLEASE, READ THE FOLLOWING TWO LINES AND EXECUTE EACH STATEMENT REPLACING THE 'N+1' WITH THE VALUE FROM PREVIOUS SELECT STATEMENT
# alter the primary key in the tables to use auto_increment, starting from the last run id +1.
# MANUALLY run the following 'SELECT' statements and replace 'N+1' with the output of the select statment adding 1 (e.g., 1+1=2).

select max(run_id) from recorder_runs;
alter table recorder_runs modify column run_id INT NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1; 

select max(event_id) from events;
alter table events modify column event_id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1; 

select max(state_id) from states;
alter table states modify column state_id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(change_id) FROM schema_changes;
ALTER TABLE schema_changes MODIFY COLUMN change_id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(id) FROM statistics;
ALTER TABLE statistics MODIFY COLUMN id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(id) FROM statistics_meta;
ALTER TABLE statistics_meta MODIFY COLUMN id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(run_id) FROM statistics_runs;
ALTER TABLE statistics_runs MODIFY COLUMN run_id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(id) FROM statistics_short_term;
ALTER TABLE statistics_short_term MODIFY COLUMN id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(attributes_id) FROM state_attributes;
ALTER TABLE state_attributes MODIFY COLUMN attributes_id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

SELECT MAX(data_id) FROM event_data;
ALTER TABLE event_data MODIFY COLUMN data_id int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=N+1;

# Add back the foreign key constraints

ALTER TABLE `states` ADD CONSTRAINT `states_ibfk_1` FOREIGN KEY (`old_state_id`)REFERENCES `states`(`state_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE `states` ADD CONSTRAINT `states_ibfk_2` FOREIGN KEY (`event_id`)REFERENCES `events`(`event_id`) ON DELETE CASCADE ON UPDATE RESTRICT;

ALTER TABLE `states` ADD CONSTRAINT `states_ibfk_3` FOREIGN KEY (`attributes_id`)REFERENCES `state_attributes`(`attributes_id`);

ALTER TABLE `statistics` ADD CONSTRAINT `statistics_ibfk_1` FOREIGN KEY (`metadata_id`)REFERENCES `statistics_meta`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;

ALTER TABLE `statistics_short_term` ADD CONSTRAINT `statistics_short_term_ibfk_1` FOREIGN KEY (`metadata_id`) REFERENCES `statistics_meta`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;

ALTER TABLE `events` ADD CONSTRAINT `events_ibfk_1` FOREIGN KEY (`data_id`) REFERENCES `event_data` (`data_id`);

Nachdem das nun abgeschlossen ist, passen wir schlussendlich noch Homeassistant an und fügen in
die configuration.yaml folgende Zeile ein:

recorder:
  db_url: mysql://<<user>>:<<passwort>>@<<host>>/<<Datenbank>>
  # db_url: !secret mariadb_url //alternative, hier werden die Daten in der "secrets.yaml" Datei gespeichert

Falls ihr die 2. Variante mit der Secrets.yaml nutzt, dann müsst ihr da folgende Zeile einfügen:

mariadb_url:  mysql://<<user>>:<<passwort>>@<<host>>/<<Datenbank>>

Zuletzt wird Homeassistant nocheinmal neugestartet und nun sollte Homeassistant neue Daten auf dem MariaDB Server speichern. Um dies zu prüfen könnt ihr in der MariaDB CLI folgendes eingeben:

mysql > show processlist;

Bei der ausgegebenen Tabelle sollte unter der Spalte “db” zumindest eine Verbindung mit der Tabelle “<<euer Datenbankname>>” bestehen. Bei mir sind es 4.


Back…