MySQL: Erste Schritte

Wie Sie mit MySQL starten

👋 Willkommen in der Stackhero-Dokumentation!

Stackhero bietet eine einsatzbereite MySQL-Cloud-Lösung, die zahlreiche Vorteile bietet, darunter:

  • Unbegrenzte Verbindungen und Übertragungen.
  • phpMyAdmin Web-UI inklusive.
  • Mühelose Updates mit nur einem Klick.
  • Optimale Performance und robuste Sicherheit durch eine private und dedizierte VM.

Sparen Sie Zeit und vereinfachen Sie Ihr Leben: Es dauert nur 5 Minuten, um die MySQL-Cloud-Hosting-Lösung von Stackhero auszuprobieren!

Wenn Sie eine schnelle Möglichkeit suchen, sich mit Ihrem MySQL-Service zu verbinden, können Sie das MySQL-URL-Format verwenden, sofern Ihr Treiber dies unterstützt:

mysql://root:<ROOT_PASSWORD>@<XXXXXX>.stackhero-network.com:<PORT>/root?useSSL=true&requireSSL=true

Wenn Sie mit Ruby arbeiten, ist das URL-Format leicht abgewandelt:

mysql2://root:<ROOT_PASSWORD>@<XXXXXX>.stackhero-network.com:<PORT>/root?reconnect=true&useSSL=true&requireSSL=true

Hier ein Beispiel, wie Sie sich mit der MySQLi-Erweiterung von PHP im objektorientierten Stil verbinden:

<?php

$hostname = '<XXXXXX>.stackhero-network.com';
$port = '<PORT>';
$user = 'root';
$password = '<ROOT_PASSWORD>';
$database = 'root'; // In diesem Beispiel wird die Datenbank "root" verwendet. Es empfiehlt sich jedoch, über phpMyAdmin eine eigene Datenbank und einen eigenen Benutzer für Ihre Anwendung anzulegen.

$mysqli = mysqli_init();
$mysqliConnected = $mysqli->real_connect($hostname, $user, $password, $database, $port, NULL, MYSQLI_CLIENT_SSL);
if (!$mysqliConnected) {
  die("Verbindungsfehler: " . $mysqli->connect_error);
}

echo 'Verbindung erfolgreich... ' . $mysqli->host_info . "\n";

$mysqli->close();

?>

Wenn Sie prozeduralen Code bevorzugen, können Sie sich so mit MySQLi verbinden:

<?php

$hostname = '<XXXXXX>.stackhero-network.com';
$port = '<PORT>';
$user = 'root';
$password = '<ROOT_PASSWORD>';
$database = 'root'; // Für optimale Sicherheit sollten Sie in phpMyAdmin eine eigene Datenbank und einen eigenen Benutzer anlegen, anstatt "root" zu verwenden.

$mysqli = mysqli_init();
$mysqliConnected = mysqli_real_connect($mysqli, $hostname, $user, $password, $database, $port, NULL, MYSQLI_CLIENT_SSL);
if (!$mysqliConnected) {
  die("Verbindungsfehler: " . mysqli_connect_error($mysqli));
}

echo 'Erfolg: ' . mysqli_get_host_info($mysqli) . "\n";

mysqli_close($mysqli);

?>

Wenn Sie PDO für den Datenbankzugriff bevorzugen, finden Sie hier ein Beispiel für die Verbindung:

<?php

$hostname = '<XXXXXX>.stackhero-network.com';
$port = '<PORT>';
$user = 'root';
$password = '<ROOT_PASSWORD>';
$database = 'root'; // Es empfiehlt sich, für Ihre Anwendung eine eigene Datenbank und einen eigenen Benutzer anzulegen.

$dsn = "mysql:host=$hostname;port=$port;dbname=$database";

$options = array(
  // Falls Sie beim Verbindungsaufbau SSL-Fehler erhalten, stellen Sie sicher, dass die richtigen CA-Zertifikate auf Ihrem System installiert sind (siehe unten).
  PDO::MYSQL_ATTR_SSL_CAPATH => '/etc/ssl/certs/',
  // PDO::MYSQL_ATTR_SSL_CA => 'isrgrootx1.pem',
  PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true,
);

$pdo = new PDO($dsn, $user, $password, $options);

$stm = $pdo->query("SELECT VERSION()");
$version = $stm->fetch();

echo "Sie sind mit einer Datenbank verbunden, die Version " . $version[0] . " ausführt\n";

?>

Wenn Sie eine Fehlermeldung wie diese sehen:

Uncaught PDOException: PDO::__construct(): SSL operation failed with code 1. OpenSSL Error messages: error:0A000086:SSL routines::certificate verify failed

liegt das wahrscheinlich daran, dass auf Ihrem System CA-Zertifikate im Verzeichnis /etc/ssl/certs/ fehlen.

Wenn Sie Zugriff auf das System haben, auf dem Ihr PHP-Code läuft, können Sie die Zertifikate wie folgt installieren:

  1. Unter Ubuntu/Debian: sudo apt-get install ca-certificates
  2. Unter Alpine Linux: apk add ca-certificates

Wenn Sie keinen direkten Zugriff haben, können Sie das Zertifikat manuell hinzufügen:

  1. Laden Sie das Zertifikat herunter: https://letsencrypt.org/certs/isrgrootx1.pem
  2. Legen Sie die Datei isrgrootx1.pem in Ihr PHP-Projekt.
  3. Kommentieren Sie die Zeile PDO::MYSQL_ATTR_SSL_CAPATH => '/etc/ssl/certs/' aus.
  4. Kommentieren Sie die Zeile PDO::MYSQL_ATTR_SSL_CA => 'isrgrootx1.pem' ein.

Wenn Sie Fehler wie diese sehen:

Fatal error: Uncaught Error: Undefined constant PDO::MYSQL_ATTR_SSL_CAPATH

oder ähnliche Meldungen, bedeutet das, dass PDO ohne MySQL-Unterstützung installiert wurde.

  1. Unter Ubuntu/Debian

Sie können die benötigte Erweiterung mit folgendem Befehl installieren:

sudo apt-get install php-mysql
  1. In Docker

Wenn Sie Docker verwenden, stellen Sie sicher, dass MySQL-Unterstützung beim Build enthalten ist. Fügen Sie dies zu Ihrer Dockerfile hinzu:

RUN docker-php-ext-install pdo pdo_mysql

### MySQL mit Symfony und Doctrine verwenden

Wenn Sie mit Symfony und Doctrine arbeiten, können Sie Ihre Verbindung wie folgt konfigurieren:

1. Bearbeiten Sie Ihre `.env`-Datei und setzen Sie die Variable `DATABASE_URL`:

DATABASE_URL="mysql://<USER>:<PASSWORD>@<XXXXXX>.stackhero-network.com:<PORT>/<DATABASE>"


1. Legen Sie dann in `config/packages/doctrine.yaml` den Treiber und die Optionen fest:

```yaml
doctrine:
    dbal:
        url: '%env(resolve:DATABASE_URL)%'
        driver: 'pdo_mysql'
        options:
            # PDO::MYSQL_ATTR_SSL_CAPATH
            1010: '/etc/ssl/certs'
            # PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT
            1014: true

Wenn Sie eine Fehlermeldung wie diese erhalten:

Uncaught PDOException: PDO::__construct(): SSL operation failed with code 1. OpenSSL Error messages: error:0A000086:SSL routines::certificate verify failed

liegt das wahrscheinlich daran, dass im Verzeichnis /etc/ssl/certs/ keine CA-Zertifikate vorhanden sind.

Wenn Sie Zugriff auf das System haben, können Sie diese wie folgt installieren:

  1. Unter Ubuntu/Debian: sudo apt-get install ca-certificates
  2. Unter Alpine Linux: apk add ca-certificates

Wenn Sie keinen direkten Zugriff haben, können Sie das Zertifikat manuell hinzufügen:

  1. Download: https://letsencrypt.org/certs/isrgrootx1.pem
  2. Legen Sie isrgrootx1.pem in Ihr Symfony-Projekt.
  3. Aktualisieren Sie config/packages/doctrine.yaml:
doctrine:
    dbal:
        url: '%env(resolve:DATABASE_URL)%'
        driver: 'pdo_mysql'
        options:
            # PDO::MYSQL_ATTR_SSL_CA
            1009: 'isrgrootx1.pem'
            # PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT
            1014: true

Um MySQL in Laravel zu konfigurieren, öffnen Sie config/database.php und passen Sie den MySQL-Abschnitt wie folgt an:

'mysql' => [
  'driver' => 'mysql',
  'host' => env('STACKHERO_MYSQL_HOST'),
  'port' => env('STACKHERO_MYSQL_PORT'),
  'username' => env('STACKHERO_MYSQL_USER'),
  'password' => env('STACKHERO_MYSQL_PASSWORD'),
  'database' => env('STACKHERO_MYSQL_USER'),
  'charset' => 'utf8mb4',
  'collation' => 'utf8mb4_unicode_ci',
  'prefix' => '',
  'prefix_indexes' => true,
  'strict' => true,
  'engine' => null,
  'sslmode' => 'require',
  'options' => extension_loaded('pdo_mysql')
    ? array_filter([
      // Bei SSL-Fehlern siehe Fehlerbehebung oben.
      PDO::MYSQL_ATTR_SSL_CAPATH => '/etc/ssl/certs/',
      // PDO::MYSQL_ATTR_SSL_CA => 'isrgrootx1.pem',
      PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true,
    ])
    : [],
],

In der Konfigurationsdatei database.php können Sie Folgendes hinzufügen:

$db['default'] = array(
  'hostname' => getenv('STACKHERO_MYSQL_HOST'),
  'port'     => getenv('STACKHERO_MYSQL_PORT'),
  'username' => getenv('STACKHERO_MYSQL_USER'),
  'password' => getenv('STACKHERO_MYSQL_PASSWORD'),
  'database' => getenv('STACKHERO_MYSQL_USER'), // Üblicherweise entspricht der Datenbankname dem Benutzernamen.
  'dbdriver' => 'mysqli',
  'dbprefix' => '',
  'pconnect' => true,
  'char_set' => 'utf8',
  'dbcollat' => 'utf8_general_ci',
  'encrypt'  => array() // Wichtig: TLS-Verschlüsselung aktivieren
);

Es ist generell sicherer, Ihre Datenbank-Zugangsdaten nicht im Code zu speichern. Stattdessen können Sie Umgebungsvariablen verwenden. So können Sie diese abrufen:

$hostname = getenv('STACKHERO_MYSQL_HOST');
$port = getenv('STACKHERO_MYSQL_PORT');
$user = getenv('STACKHERO_MYSQL_USER');
$password = getenv('STACKHERO_MYSQL_PASSWORD');
$database = getenv('STACKHERO_MYSQL_USER'); // Üblicherweise entspricht der Datenbankname dem Benutzernamen.

Die Anbindung von WordPress an Stackhero für MySQL ist unkompliziert. Sie müssen lediglich Ihre wp-config.php wie folgt anpassen:

define('DB_HOST', '<XXXXXX>.stackhero-network.com');
define('DB_PORT', '<PORT>');
define('DB_NAME', 'root');
define('DB_USER', 'root');
define('DB_PASSWORD', '<yourPassword>');

// TLS-Verschlüsselung aktivieren (auch als SSL bekannt)
define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL);

Der entscheidende Schritt ist hier die Aktivierung der TLS-(SSL-)Verschlüsselung. Ohne diese wird Ihre Verbindung nicht wie erwartet funktionieren.

Um das MySQL X-Protokoll zu verwenden, installieren Sie das offizielle xdevapi-Paket:

npm install @mysql/xdevapi

Hier ein Beispielskript:

const mysqlx = require('@mysql/xdevapi');

(async () => {
  // Verbindung zu MySQL über das MySQL X-Protokoll
  const session = await mysqlx.getSession({
    host: '<XXXXXX>.stackhero-network.com',
    port: '<PORT>',
    user: 'root',
    password: '<ROOT_PASSWORD>'
  });

  // Schema (Datenbank) anlegen, falls nicht vorhanden
  const schemaExists = await session.getSchema('stackherotest').existsInDatabase();
  if (!schemaExists) {
    await session.createSchema('stackherotest');
  }

  // Tabelle 'users' anlegen, falls nicht vorhanden
  const tableExists = await session
    .getSchema('stackherotest')
    .getTable('users')
    .existsInDatabase();
  if (!tableExists) {
    await session
      .sql('CREATE TABLE `stackherotest`.`users` '
        + '('
        + '`userId` INT UNSIGNED NOT NULL,'
        + '`name` VARCHAR(128) NOT NULL,'
        + '`address` TEXT NOT NULL,'
        + '`email` VARCHAR(265) NOT NULL'
        + ') '
        + 'ENGINE = InnoDB;')
      .execute();
  }

  // Beispielbenutzer einfügen
  await session
    .getSchema('stackherotest')
    .getTable('users')
    .insert('userId', 'name', 'address', 'email')
    .values(
      Math.round(Math.random() * 100000),
      'User name',
      'User address',
      '[email protected]'
    )
    .execute();

  // Anzahl der Benutzer zählen
  const usersCount = await session
    .getSchema('stackherotest')
    .getTable('users')
    .count();

  console.log(`Es gibt jetzt ${usersCount} Einträge in der Tabelle "users"`);

  // Verbindung schließen
  await session.close();

})().catch(error => {
  console.error('');
  console.error('Ein Fehler ist aufgetreten!');
  console.error(error);
  process.exit(1);
});

Wenn Sie das klassische Protokoll bevorzugen, können Sie das mysql2-Paket mit Promise-Unterstützung verwenden. Installieren Sie es mit:

npm install mysql2

Beispielnutzung:

const mysql = require('mysql2/promise');

(async () => {
  const db = await mysql.createConnection({
    host: '<XXXXXX>.stackhero-network.com',
    port: '<PORT>',
    user: 'root',
    password: '<ROOT_PASSWORD>'
  });

  // Datenbank bei Bedarf anlegen
  await db.query('CREATE DATABASE IF NOT EXISTS stackherotest');

  // Tabelle bei Bedarf anlegen
  await db.query('CREATE TABLE IF NOT EXISTS `stackherotest`.`users` '
    + '('
    + '`userId` INT UNSIGNED NOT NULL,'
    + '`name` VARCHAR(128) NOT NULL,'
    + '`address` TEXT NOT NULL,'
    + '`email` VARCHAR(265) NOT NULL'
    + ') '
    + 'ENGINE = InnoDB;');

  // Beispielbenutzer einfügen
  await db.query(
    'INSERT INTO `stackherotest`.`users` (`userId`, `name`, `address`, `email`) VALUES ?',
    [
      [
        Math.round(Math.random() * 100000),
        'User name',
        'User address',
        '[email protected]'
      ]
    ]
  );

  // Benutzer zählen
  const [ usersCount ] = await db.query('SELECT COUNT(*) AS `cpt` FROM `stackherotest`.`users`');
  console.log(`Es gibt jetzt ${usersCount[0].cpt} Einträge in der Tabelle "users"`);

  // Verbindung schließen
  await db.end();

})().catch(error => {
  console.error('');
  console.error('Ein Fehler ist aufgetreten!');
  console.error(error);
  process.exit(1);
});

Um sich von Node.js, NestJS oder TypeORM zu verbinden, können Sie die Option ssl wie folgt hinzufügen:

TypeOrmModule.forRoot({
  type: 'mysql',
  host: '<XXXXXX>.stackhero-network.com',
  port: <PORT>,
  username: 'root',
  password: '<ROOT_PASSWORD>',
  database: 'root',
  entities: [],
  synchronize: true,
  ssl: {}
});

Wenn Sie Prisma nutzen, sorgt die Option sslaccept=strict für eine verschlüsselte Verbindung. Beispielkonfiguration:

datasource db {
  provider = "mysql"
  url = "mysql://root:<ROOT_PASSWORD>@<XXXXXX>.stackhero-network.com:<PORT>/root?sslaccept=strict"
}

Falls das Modul mysqlclient noch nicht installiert ist, können Sie es mit folgendem Befehl installieren:

pip install mysqlclient

Wenn Sie beim Installieren den Fehler Exception: Can not find valid pkg-config name erhalten, müssen Sie eventuell das Paket libmysqlclient hinzufügen. Unter Ubuntu/Debian geht das mit: apt-get update && apt-get install --no-install-recommends -y libmysqlclient-dev

Für erste Tests können Sie das Passwort direkt in Ihrer settings.py speichern. Für den produktiven Einsatz empfiehlt es sich jedoch, Umgebungsvariablen zu verwenden (siehe unten).

Bearbeiten Sie Ihre settings.py wie folgt:

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.mysql',
    'HOST': '<XXXXXX>.stackhero-network.com',
    'PORT': '<PORT>',
    'OPTIONS': {
      'ssl_mode': 'REQUIRED',
    },
    'NAME': 'root',
    'USER': 'root',
    'PASSWORD': '<ROOT_PASSWORD>'
  }
}

Hinweis: Dieses Beispiel dient nur zu Testzwecken und ist für Produktionsumgebungen nicht empfohlen!

Nachdem Sie die Verbindung erfolgreich getestet haben, können Sie auf eine sicherere Variante mit django-environ umstellen, um Umgebungsvariablen zu verwalten.

Installieren Sie zunächst das Paket:

pip install django-environ

Aktualisieren Sie dann Ihre settings.py:

import environ
env = environ.Env()
environ.Env.read_env()

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.mysql',
    'HOST': env('STACKHERO_MYSQL_HOST'),
    'PORT': env('STACKHERO_MYSQL_PORT'),
    'OPTIONS': {
      'ssl_mode': 'REQUIRED',
    },
    'NAME': 'root',
    'USER': 'root',
    'PASSWORD': env('STACKHERO_MYSQL_ROOT_PASSWORD')
  }
}

Erstellen oder bearbeiten Sie die .env-Datei im gleichen Verzeichnis wie settings.py und fügen Sie Folgendes hinzu:

STACKHERO_MYSQL_HOST=<XXXXXX>.stackhero-network.com
STACKHERO_MYSQL_PORT=<PORT>
STACKHERO_MYSQL_ROOT_PASSWORD=<ROOT_PASSWORD>

Um Ihre Zugangsdaten zu schützen, können Sie .env zu Ihrer .gitignore hinzufügen:

echo ".env" >> .gitignore

Um Ihre Spring-Anwendung zu verbinden, setzen Sie die Umgebungsvariable SPRING_DATASOURCE_URL mit Ihrer Datenbank-URL und achten Sie darauf, sie mit jdbc: zu beginnen:

SPRING_DATASOURCE_URL=jdbc:mysql://root:<ROOT_PASSWORD>@<XXXXXX>.stackhero-network.com:<PORT>/root?useSSL=true&requireSSL=true

Hier ein Beispiel, wie Sie Ihre Grails-Anwendung für die Verbindung zu MySQL konfigurieren:

dataSource {
  pooled = true
  driverClassName = "com.mysql.cj.jdbc.Driver"
  dialect = org.hibernate.dialect.MySQL8Dialect
  // SSL-spezifische Eigenschaften
  properties {
    useSSL = true
    requireSSL = true
    verifyServerCertificate = true
    sslMode = "REQUIRED"
  }
}

environments {
  production {
    dataSource {
      dbCreate = "none"
      url = "jdbc:mysql://" + System.env.STACKHERO_MYSQL_HOST + ":" + System.env.STACKHERO_MYSQL_PORT + "/root?useSSL=true&requireSSL=true&verifyServerCertificate=true&sslMode=required" // Sie können "/root" durch Ihre gewünschte Datenbank ersetzen.
      username = "root" // Es empfiehlt sich, einen eigenen Benutzer für Ihre Anwendung zu erstellen.
      password = System.env.STACKHERO_MYSQL_ROOT_PASSWORD
      properties {
        maxActive = 50
        minEvictableIdleTimeMillis = 1800000
        timeBetweenEvictionRunsMillis = 1800000
        numTestsPerEvictionRun = 3
        testOnBorrow = true
        testWhileIdle = true
        testOnReturn = false
        validationQuery = "SELECT 1"
      }
    }
  }
}

Für mehr Sicherheit empfiehlt es sich, einen eigenen Benutzer für Ihre Anwendung zu erstellen, anstatt den Benutzer "root" zu verwenden. Dies können Sie einfach über phpMyAdmin erledigen:

  1. Wählen Sie in phpMyAdmin im oberen Menü User accounts aus.

  2. Klicken Sie auf Add user account.

  3. Füllen Sie das Formular zur Benutzererstellung aus:

    • Geben Sie einen Kontonamen ein (in der Regel den Namen Ihrer Anwendung)
    • Klicken Sie auf Generate password für ein sicheres Passwort und kopieren Sie es in die Zwischenablage
    • Wählen Sie Create database with same name and grant all privileges

Nach dem Absenden des Formulars verfügen Sie über einen neuen Benutzer und eine eigene Datenbank, die denselben Namen wie Ihr Benutzerkonto trägt.