Verbindung zur Datenbank scheitert (MariaDB)

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Hallo,
ich bin neu hier im Forum und möchte kurz was zu mir sagen. Ich bin Fan von Raspi & Co und bin derzeit wieder an einem Projekt. In einem Speziellen Forum dazu bin ich zwar auch, aber wenn man da eine Frage nicht 100% korrekt formuliert oder man einfach Neuling bei einer Sache ist, so bekommt man leider oft einen dummen Spruch anstatt Hilfe.
Nun bin ich hier gelandet und habe gesehen anhand von Beiträgen dass noch mehr User da sind die mit ähnlicher Hardware bauen.

Mein Projekt ist soweit fast fertig bis auf die Tatsache, dass ich noch gerne ein Feature hätte, dass erfaßte Daten in eine Datenbank schreibt.
Auf dem Raspi sind MariaDB, myphpadmin und Python (2 und 3) nebast anderen Sachen installiert.

Eine Datenbank habe ich mit myphpadmin bereits angelegt. Die Datenbank besteht aus einer Tabelle mit 7 Feldern. Eine extra User für das Handling mit der Datenbank habe ich angelegt. Der Connector für Python 2.7 zu MariaDB/MySQL ist installiert mit:

sudo apt-get update
sudo apt-get -y install python-mysql.connector

Im Python Skrip importiere ich die Module mit:

import mysql;
import mysql.connector;

Bis dahin scheint alles noch korrekt zu laufen.

Ab hier habe ich im Netz unterschiedliche Ausführungen gefunden um mit der Datenbank zu verbinden. Jedoch hat keine Funktioniert so dass eine Fehlermeldung kam. Ok, normal liest man die Fehlermeldung und sucht;) Da ich den Raspi aber Headless betreibe sehe ich diese erst mal nicht beim booten. Nun hab ich einen Monitor per HDMI ran gehängt um die Fehlermeldung lesen zu können. Leider stimmt beim booten des Raspis die Auflösung nicht und smoit wird der hintere Teil der Meldungen abgeschnitten. Murphy halt mal wieder.

Jetzt hatte ich eigentlich vor hier den Teil zu Posten den ich mit dem Handy fotografieren konnte. Bild nicht aufgenommen - noch mal Murphy.

Nun erst mal die Frage wie würdet Ihr überhaupt zu Datenbank verbinden?

Verbinde ich da zur Datenbank oder dann zur Tabelle?

Ich versuche die Infos noch nachzuliefern.

Grüße

Manic
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Bitte keine Bildschirme abfotografieren wenn es sich um Text handelt. Verbinde Dich per SSH mit dem Raspi und lass da Deine Verbindungstests zur Datenbank laufen, dann kannst Du Ausgaben vom Programm auch einfach als Text kopieren.

Wenn die Datenbank beim Booten schon nicht startet weil irgend etwas falsch konfiguriert ist, dann braucht man das auch nicht *beim* Bootvorgang am Bildschirm mitlesen, sondern kann sich später das Bootprotokoll in der SSH-Sitzung anschauen.

Verbinden würde ich mich so wie das in der MySQL/Connector-Dokumentation beschrieben wird. Da gibt's Code-Beispiele, Tutorials, und eine API-Referenz.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Hallo,

keine Angst - ein Bild poste ich hier nicht.

Meintest Du mit dem Verbindungsversuch in der Python Konsole während ich per SSH auf dem Raspi bin?

Theoretisch kann ich doch auch ein Toll auf dem Laptop/PC hernehmen und versuchen Verbindung mit der Datenbank zu bekommen, oder?

Grüße

Manic
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Manic: Nur wenn Du die Datenbank so konfiguriert hast, dass sie Verbindungen von aussen erlaubt, was zumindest nicht die Grundeinstellung sein dürfte, und was man für den Fall das Anwendung und Datenbank auf dem selben Rechner laufen, nicht gerne macht. Selbst wenn man eine Verbindung von aussen zulässt, schränkt man die für gewöhnlich auf bestimmte Rechner ein.

Im Fall von Anwendung und Datenbank auf dem selben Rechner tunnele ich persönlich lieber den Datebankport per SSH zu meinem Arbeitsrechner wenn auf dem ein Werkzeug für den Datenbankzugriff läuft. Oder man installiert sich Adminer oder phpMyAdmin auf dem Datenbankrechner falls der sowieso schon einen Webserver laufen hat.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Hallo,

also der Raspi hängt nur zur Konfiguration bei mir im Heimnetz. Von Extern muss keiner drauf zugreifen. Später spannt der Raspi sein eigenes lokales Netz auf an dem sich die Clients anmelden. Der Raspi läuft auch nicht permanent, so dass man sich drauf einrichten könnte. Die Sorge dass übers Internet einer es dauerhaft versucht ist fast nicht gegeben.

Ich werde mir mal die Konfiguration ansehen. Ach ja NginX hab ich auch noch laufen, das hatte ich vergessen.
Tholo
User
Beiträge: 177
Registriert: Sonntag 7. Januar 2018, 20:36

Sobald du via SSH auf dem RPI bist kannst du über das SSH Terminal auf auf MariaDB Zugreifen und dir zb die Tabellen anschauen.
Hier is ein Tutorial wie man mit SSH auf den Pi kommt

Ich hab 17 RPI, Odroids etc laufen und greife auf alle ausschließlich via SSH zu. Das is kein Problem aber du könnste ggf auch mit einem VNC Viewer das Bild auf den PC bringen. Innerhalb des Heimnetzwerkes ist das kein Problem
https://www.realvnc.com/de/raspberrypi/
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Hallo Tholo,

auf den Raspi per SSH zu kommen ist nicht das Problem, das hab ichs chon immer mit Putty gemacht.

Ich werde jetzt erst mal mit phpmyadmin ein paar Datensätze anlegen und dann abfragen darin machen ob die Datenbank auch erst mal so funktioniert.

Grüße

Manic
Tholo
User
Beiträge: 177
Registriert: Sonntag 7. Januar 2018, 20:36

Da ich gerade an diesem Feld arbeite, hier mal ein Beispielcode

Code: Alles auswählen

import mysql.connector #diesen nutzt da ja auch
from configparser import ConfigParser # persönliche Daten niemals im Code halten! Daher der weg mit dem Configparser

config = ConfigParser()
config.read("learn.ini") #Name der Ini Datei im gleichen Verzeichnis
section = "MySql" # siehe Docstring -> Aufbau der Ini

"""[MySql]
mysqldriver = mysqlconnector
mysqluser = Username
mysqlpw = password
mysqlhost = localhost
mysqlport = 3306
mysqldbname = dbname"""

dbconfig = {}
dbconfig["host"] = config.get(section, "mysqlhost")
dbconfig["port"] = config.get(section, "mysqlport")
dbconfig["user"] = config.get(section, "mysqluser")
dbconfig["password"] = config.get(section, "mysqlpw")
dbconfig["database"] = config.get(section, "mysqldbname")


conn = mysql.connector.connect(**dbconfig)
cursor = conn.cursor()
_SQL = """describe log""" #Gibt die Table Infos wieder
cursor.execute(_SQL)
result = cursor.fetchall()
print(result )
Noch besser is wohl die Nutzung von SQLAlchemy aber da bin ich selbst noch an der einarbeitung
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Manic hat geschrieben: Dienstag 3. Juli 2018, 11:03 Nun erst mal die Frage wie würdet Ihr überhaupt zu Datenbank verbinden?
Testweise erstmal den Datenbank-Server auf dem Raspberry Pi starten, wenn der Dienst läuft, würde ich mit dem Standard-Benutzer direkt lokal via Shell zum Datenbank-Server konnektieren (für MySQL gibt es bspw. einen Mysql-Client, das wird bei MariaDB nicht anders sein, letzteres habe ich nur nie benutzt)

Einmal mit dem DB-Server verbunden kannst du nun alle vorhandenen Datenbanken anzeigen lassen oder dich ggf. mit einer dieser verbinden. Im Anschluss kannst du dann die SQL-typischen Kommandos zum Erstellen, Manipulieren oder Auslesen von Tabellen durchführen.
Manic hat geschrieben: Dienstag 3. Juli 2018, 11:03 Verbinde ich da zur Datenbank oder dann zur Tabelle?
Wie schon geschrieben, verbinden *tut* man sich mit dem Datenbank-Server / Datenbank, die Tabelle spricht man über einen sogenannten Cursor der auf Grundlage der Verbindung erstellt wird. Vielen Datenbank-Schnittstellen / APIs übergibt man bereits bei der Initialisierung die entsprechenden Informationen wie Host, Benutzername/Passwort und Datenbank.

Beim Debuggen ist erstmal wichtig, dass du die Datenbank außerhalb von Python problemlos ansprechen kannst. Dann kannst du im nächsten Schritt deinen Code prüfen. Wie __blackjack__ schon erwähnte müssen dem Benutzer natürlich die Berechtigungen gegeben werden, vorallem muss man berücksichtigen dass der Datenbank-Server nicht nur auf "localhost" Verbindungen entgegen nimmt, sondern via 0.0.0.0, sonst wirst du keine Remote-Verbindung zustande bekommen. Der Benutzer benötigt überdies die entsprechenden Priviledges auf der Datenbank, z.B. "hans"@"10.x.x.x."
When we say computer, we mean the electronic computer.
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tholo: Warum haben die ganzen Schlüssl in der INI-Datei noch mal einen `mysql`-Präfix? Die Section heisst doch schon so, damit bringt der Präfix keine weitere Information für den Leser.

Mit ``dict(config['MySql'])`` würdest Du die komplette MySql-Section als Wörterbuch bekommen. Wenn die Namen der Schlüssl dann die Namen der Schlüsselwortargumente von `connect()` hätten, könntest Du Dir `dbconfig` komplett sparen: ``mysql.connector.connect(dict(config['MySql']))``.

Ich weiss das war hier nur zur Demonstration, aber literale Zeichenketten sind keine Kommentare und sollten nicht als solche missbraucht werden. Wenn Du den Code beispielsweise mit Sphinx verarbeiten wollen würdest, dann würde der INI-Inhalt als Dokumentation der Variable `section` enden.

Warum der führende Unterstrich bei `_SQL`?

Weil Du SQLAlchemy erwähnst, da steht was in der Dokumentation was mich Abstand von MySql/Connector nehmen lassen würde:
The mysqlconnector driver has many issues that have gone unresolved for many years and it recommended that mysqlclient or pymysql be used if possible; as of June 27, 2018:
Und dann folgt eine kurze Liste mit Problemen die nicht gut klingen. Unter anderem Speicherlecks, das man Unicode nicht voll nutzen kann, und Deadlocks bei SELECT..FOR UPDATE. Klingt irgendwie nicht vertrauenerweckend.

SQLAlchemy (ungetestet):

Code: Alles auswählen

from sqlalchemy import create_engine

engine = create_engine('mysql+mysqlconnector://user:password@host/dbname')
print(engine.execute('DESCRIBE LOG').fetchall())
Vorteil von den Verbindungs-URLs ist, das man da nur einen Wert für speichern muss in der INI-Datei.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Tholo
User
Beiträge: 177
Registriert: Sonntag 7. Januar 2018, 20:36

__blackjack__ hat geschrieben: Mittwoch 4. Juli 2018, 10:16 @Tholo: Warum haben die ganzen Schlüssl in der INI-Datei noch mal einen `mysql`-Präfix? Die Section heisst doch schon so, damit bringt der Präfix keine weitere Information für den Leser.
Du hast Recht. Das hab ich beim erstellen einfach nicht bedacht.
__blackjack__ hat geschrieben: Mittwoch 4. Juli 2018, 10:16 Mit ``dict(config['MySql'])`` würdest Du die komplette MySql-Section als Wörterbuch bekommen. Wenn die Namen der Schlüssl dann die Namen der Schlüsselwortargumente von `connect()` hätten, könntest Du Dir `dbconfig` komplett sparen: ``mysql.connector.connect(dict(config['MySql']))``
Ich hab beim erstellen des Codes wirklich darüber nachgedacht. Wahrscheinlich nicht lang genug. Zu meiner Verteidigung. In der Ini steht alles mögliche drin. AUf Keywords die Mysql.Connector nicht braucht. SQLAlchemy allerdings schon.
Aber ist ja kein Abbruch das anders zu stukturieren. Was ich jetzt auch getan habe.
__blackjack__ hat geschrieben: Mittwoch 4. Juli 2018, 10:16 Ich weiss das war hier nur zur Demonstration, aber literale Zeichenketten sind keine Kommentare und sollten nicht als solche missbraucht werden. Wenn Du den Code beispielsweise mit Sphinx verarbeiten wollen würdest, dann würde der INI-Inhalt als Dokumentation der Variable `section` enden.
Ja war wirklich nur hier im Forum so.Da ich nicht wollte das der TE dann nicht nachvollziehen kann, wie die Ini aussehen müsste.
__blackjack__ hat geschrieben: Mittwoch 4. Juli 2018, 10:16 Warum der führende Unterstrich bei `_SQL`?
Weil dieser Code sich auf einem Lernbeispiel von Paul Barry bezieht. Und es einfach da so genannt wurde.
__blackjack__ hat geschrieben: Mittwoch 4. Juli 2018, 10:16 Weil Du SQLAlchemy erwähnst, da steht was in der Dokumentation was mich Abstand von MySql/Connector nehmen lassen würde:
The mysqlconnector driver has many issues that have gone unresolved for many years and it recommended that mysqlclient or pymysql be used if possible; as of June 27, 2018:
Und dann folgt eine kurze Liste mit Problemen die nicht gut klingen. Unter anderem Speicherlecks, das man Unicode nicht voll nutzen kann, und Deadlocks bei SELECT..FOR UPDATE. Klingt irgendwie nicht vertrauenerweckend.
Als Alternative wäre dann nach kurzem Blick wohl eher pymysql eine Wahl
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Hallo,

erst mal wow für die Resonanz auf meine Frage. Leider konnte ich bis jetzt noch nichts weiter dran machen.

Vorhin habe ich per phpmyadmin in meiner Datenbank in der existierenden Tabelle 3 Datensätze angelegt. Die Suche hat entsprechend funktioniert. Ich kann also sagen, dass die Datenbank soweit läuft.

Im nächsten Schritt hatte ich vor von einem Windowsrechner der im gleichen Netz ist auf die Datenbank zuzugreifen. Also Tool habe ich folgendes gefunden und aufgespielt: https://portableapps.com/apps/developme ... r_portable

Gewählte Einstellungen: MySQL/MariaDB
Connection Name: selbst frei gewählt
Host Name: hier hab ich die IP des Raspis genommen, da er über den Hostnamen nichts findet
Port: 3306
User Name: definierten User in phpmyadmin mit zugeh. PW
Database: Name der Datenbank, nicht der Tabelle

Er bringt: Cannot connct to Server on host......
Socket Error Code 10060:($274C)


Über den Socket Error vermute ich, dass MariaDB auf die Lokale Verwendung noch eingestellt ist. Seh ich das richtig? Wenn dann wäre mein nächster Schritt die beiden betreffenden Zeilen die dafür zuständig sind zu kommentieren.

Grüße

Manic
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also wenn Du die noch nicht für was anderes als localhost eingestellt hast, dann sollte sie von aussen nicht erreichbar sein. Wenn sie von aussen erreichbar ist, musst Du noch dem DB-Benutzer mit dem Du die Verbindung herstellen möchtest, das Recht dazu geben. Das geht mit phpMyAdmin über ich glaube „Privileges“ heisst der Menüpunkt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Ok, das werde ich spätestens heute Abend mal ausprobieren. Ein Backup der Speicherkarte habe ich schon gemacht, so dass ich notfalls wieder einen definierten Ausgangspunkt habe.

Ping auf den Raspi haut hin das hab ich vorhin proforma mal getestet.

Edit:
Ich war jetzt mal mit phpmyadmin noch mal in der Benutzerkontenübersicht:
3 User sind derzeit angelegt: phpmyadmin, root, db_user

In der tabellarischen übersicht der User hab ich bei phpmyadmin und root in der Spalte Hostname den Eintrag localhost
Beim User db_user habe ich in der gleichen Spalte ein % stehen. Das sollte schon das sein was Du meinst. Bei den Globalen rechten ist hier SELECT, INSERT, UPDATE, DELETE, FILE eingetragen. Die anderen beiden haben ALL PRIVILEGES.

Ist es dann zwingend, dass der User db_user dann von außerhalb kommt oder kann der dann auch localhost sein? Sonst müßte ich ja dem User db_user das Recht auch noch geben.
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn da `%` in der Host-Spalte steht kann der sich von überall verbinden wenn das DBMS das erlaubt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Hallo,
ich habe jetzt noch einen versuch gemacht, scheitere aber an der gleichen Sache wieder.
Der PHP Code dazu lautet:

Code: Alles auswählen

import os, sys, time
import RPi.GPIO as GPIO
import mysql.connector as mariadb
mariadb_connection = mariadb.connect(host='RaPi', port=3306, user='dbuser', Password='passwort', database='NameDatenbank')
cursor = mariadb_connection.cursor()
Wenn der Raspi startet dann ist die erste Meldung am Ende des Dumps zum Datenbankzugriff die vorletzte Zeile des von mir geposteten Codes (mariadb_connection = ...)

Die letzte Zeile der Fehlermeldung steht:
mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL Server on'RaPi:3306' (111 Connection refused)

Bei database steht der Name der Datenbank drin, nicht der Name der Tabelle in der Datenbank.

Wie kann ich den Fehler jetzt noch eingrenzen?
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Manic: Schauen was die Protokolldatei von MariaDB dazu sagt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Welche Protokolldatei meinst Du bzw wo finde ich die?

Ich habe mal kurz in der Hilfe zu MariaDB geschaut aber da scheint es ja unterschiedliche zu geben.
Manic
User
Beiträge: 10
Registriert: Dienstag 3. Juli 2018, 09:59

Ich habe nun mal geschaut. In Pfad /var/lib/mysql/ sollte laut meiner Info eine hostname.err (also RaPi.err) sein. Da ist aber nichts.

In den angegebenen Verzeichnis finde ich folgende Einträge:

NameDatenbank (also den von mir in phpmyadmin angelegten Datenbank)
aria_log.00000001
aria_log_control
Debian-10.1.flag
ibdata1
ib_logfile0
ib_logfile1
multi-master.info
mysql
Performance_schema
phpmyadmin
tc.log
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hast Du denn den Server so konfiguriert, dass er auch auf Verbindungen von aussen lauscht, und nicht nur auf localhost bzw. 127.0.0.1?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten