Inmitten der stattfindenden digitalen Transformation ist eine leistungsfähige Datenverwaltung nicht nur ein entscheidender Faktor, sondern das unumstrittene Herzstück des Erfolgs. Die gezielte Organisation und Nutzung von Daten spielt eine Schlüsselrolle für Unternehmen aller Größenordnungen. Eine Datenbank, die in diesem Kontext immer wieder genutzt wird, ist PostgreSQL.
Dieses relationale Datenbankverwaltungssystem ist eine kluge Entscheidung für Entwickler und Unternehmen, die Bedarf an erweiterten Datentypen und Index-Optionen haben. Darüber hinaus sind hier komplexe Datenmodelle realisierbar. Und als wäre das noch nicht genug, kann man benutzerdefinierte Datentypen, Constraints und Trigger-Funktionen erstellen.
PostgreSQL hat aber noch weit mehr interessante Features zu bieten wie vollständige ACID-Transaktionen oder die Multi-Version Concurrency Control. Erstes ermöglicht eine zuverlässige Datenintegrität und Letzteres sorgt für eine effiziente Handhabung von Lese- und Schreibzugriffen, insbesondere in Umgebungen mit hoher Konkurrenz.
In diesem Beitrag stehen nicht ausschließlich die Vorzüge von PostgreSQL im Fokus, noch dreht sich der Artikel um den Entwurf von Datenbanken oder gar deren Modellierung. Vielmehr werde ich dir aufzeigen, wie du mithilfe von Red Hat 9 einen simplen PostgreSQL-Datenbankserver einrichten kannst. Die grundlegende Härtung des Systems werde ich dabei auch noch kurz anschneiden.
1. PostgreSQL-Repo hinzufügen:
Die Standard-Paketquellen von Red Hat bieten lediglich PostgreSQL in der Version 13 an, deren Supportzyklus jedoch bereits Ende 2025 ausläuft. Obwohl man mithilfe eines DNF-Moduls bereits Version 15 einsetzen kann, werde ich in diesen Beitrag den klassischen Weg gehen. Die Rede ist natürlich vom offiziellen Repository, um stets die neusten Versionen und Updates installieren zu können.
Seit Anfang November 2023 ist PostgreSQL 16 als Stable-Release verfügbar. Diese Version wird bis Ende 2028 mit Updates und neuen Features versorgt. Allerdings lassen sich nach dem Einbinden auch ältere Releases bis hin zu PostgreSQL 11 in Betrieb nehmen. Das Repository lässt sich mit nur einem einzigen Kommando in Red Hat einbinden:
dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
2. PostgreSQL-Paket installieren:
Bevor du mit der Installation beginnen kannst, ist es erforderlich, das vorhandene PostgreSQL-Modul zu deaktivieren. Doch bevor ich darauf genauer eingehe, möchte ich dir kurz erklären, was ein solches Modul überhaupt ist. Mit der Implementierung von DNF als Standard-Paketmanager sind sogenannte Module ins Spiel gekommen.
Zum gegenwärtigen Zeitpunkt kann man damit PostgreSQL in Version 15 ausrollen. Zu beachten ist hierbei, dass man dabei zwischen 2 Profilen auswählen kann. Da wäre einerseits die Client- und andererseits die Serverkomponente. Hinter einem Modul verbirgt sich also eine organisatorische Einheit, die verschiedene Komponenten, Einstellungen und Erweiterungen bündelt.
Im Verlauf der Zeit werden für verschiedene Hauptversionen separate Module verfügbar sein. Die Deaktivierung des vorhandenen PostgreSQL-Moduls ist notwendig, um Updateprobleme mit dem über das Repository installierten PostgreSQL-Server zu vermeiden. Sobald dieser Schritt erfolgreich umgesetzt wurde, steht der Installation des neuesten Hauptreleases nichts mehr im Wege:
dnf -qy module disable postgresql
dnf install -y postgresql16-server
3. PostgreSQL konfigurieren:
Die individuelle Anpassung der PostgreSQL-Konfiguration ist von zentraler Bedeutung, um die Datenbank optimal auf spezifische Anforderungen und Leistungsziele auszurichten. Da jede Anwendung aber unterschiedliche Anforderungen an einen Datenbankserver stellt, werde ich in den folgenden Zeilen nur auf die absoluten Basics eingehen können.
Besonders großen Wert werde ich dabei auf die Verbindungsparameter in der postgresql.conf im Verzeichnis /var/lib/pgsql/16/data/ legen. Dort kann man unter anderem festlegen, wie viele gleichzeitige Verbindungen erlaubt sind, wann der Timeout-Wert überschritten wird oder unter welcher IP-Adresse der PostgreSQL-Server Anfragen entgegennimmt.
Weiterhin ermöglicht diese Konfigurationsdatei auch die granulare Einstellung der verschiedenen Caches und dem Logging. Außerdem kann man die Performance steigern, indem man eine Feinabstimmung bei effective_io_concurrency, random_page_cost und maintenance_work_mem vornimmt. Im Folgenden werde ich auf einige der entscheidenden Konfigurationseinstellungen eingehen:
# Networking
listen_addresses = '*' # Hier könnte auch eine spezifische IP-Adresse angegeben werden.
max_connections = 100 # Begrenzt die maximale Anzahl gleichzeitiger Verbindungen zur Datenbank auf 100.
idle_in_transaction_session_timeout = 60000 # Maximale Dauer, die eine Transaktion im Idle verweilen kann, bis diese automatisch abgebrochen wird. Die Zeitangabe erfolgt in Millisekunden.
# Logging
logging_collector = on # Dedizierte Logs werden erstellt
log_directory = '/var/log/postgresql/'
log_filename = 'postgresql.log'
log_connections = yes # Aktiviert die Protokollierung von Verbindungsinformationen, was hilfreich für das Monitoring und die Fehlerbehebung sein kann.
log_error_verbosity = default # Terse zeigt grundlegende Informationen an, Standard verfügt noch über Kontextinformationen und verbose steht für das Maximum an Infos.
log_statement = 'none' # Diese Einstellung bestimmt, welche SQL-Anweisungen protokolliert werden. ddl: Nur Datenbankschemaänderungen protokollieren oder mod: Datenänderungsanweisungen (INSERT, UPDATE, DELETE) protokollieren.
# Cache
shared_buffers = 3GB # Diese Einstellung definiert den Speicherpool, der von PostgreSQL für die gemeinsame Nutzung von Datenpuffern verwendet wird.
effective_cache_size = 3GB # Diese Einstellung definiert, wie viel restlichen Arbeitsspeicher der Server noch zur Verfügung stehen hat.
# Maintenance
work_mem = 128MB # Größe des Arbeitsspeichers, der für Sortieroperationen und Hash-Joins genutzt wird.
maintenance_work_mem = 1GB # Größe des Arbeitsspeichers, der für Wartungsaufgaben wie VACUUM oder Indexerstellung verwendet wird.
autovacuum = on # Eine Funktion, die automatisch veraltete oder nicht mehr benötigte Daten löscht.
# Tuning
checkpoint_completion_target = 0.9 # Gibt an, wann der automatische
Checkpoint-Prozess abgeschlossen sein sollte, um die Schreibvorgänge zu optimieren und den Durchsatz zu erhöhen.
effective_io_concurrency = 2 # Ein höherer Wert bedeutet, dass PostgreSQL eine höhere Anzahl gleichzeitiger I/O-Operationen durchführt.
4. PostgreSQL starten:
Nachdem die aufwändige Konfiguration des Datenbankservers abgeschlossen ist, geht es nun darum, die PostgreSQL-Datenbank zu initialisieren. Bei diesem Schritt wird ein neues PostgreSQL-Datenbankcluster eingerichtet. Und keine Sorge, in unserem Fall handelt es sich um ein ganz einfaches Single-Node-Cluster. Nach wenigen Sekunden ist dieser Vorgang abgeschlossen und es kann weiter gehen.
Nun muss noch der PostgreSQL-Service so konfiguriert werden, dass er automatisch beim Systemstart aktiviert wird. Es ist jedoch wichtig zu betonen, dass dieser Schritt nicht ohne das anschließende Starten des Dienstes abgeschlossen ist. Erst dann ist die PostgreSQL-Instanz grundlgend betriebsbereit. Natürlich fehlt noch die finale Konfiguration in Form von Zugriffsberechtigungen & Co.
/usr/pgsql-16/bin/postgresql-16-setup initdb
systemctl enable postgresql-16
systemctl start postgresql-16
5. Datenbank samt User anlegen:
Damit eine Anwendung mit dem frisch aufgesetzten PostgreSQL-Server kommunizieren kann, muss man noch 4 kleine Befehle absetzen. Im ersten Schritt wird man zum Superuser Postgres und öffnet dabei gleich noch das PSQL-Terminal, in dem man SQL-Befehle ausführen kann. Dort angekommen legt man eine Datenbank für die spätere Applikation an.
Natürich benötigt man auch noch einen User, der später Tabellen anlegt und diese mit Daten befüllt. Das gelingt aber nur, wenn er zum Abschluss der Arbeiten noch alle notwendigen Berechtigungen für diese eine Datenbank bekommt. In diesem Beispiel erhält der zuvor angelegte User die vollen Lese- und Schreibzugriffe sowie alle anderen Rechte, um Operationen durchführen zu können.
su - postgres psql
postgres=# create database <mydb>;
postgres=# create user <myuser> with encrypted password '<mypass>';
postgres=# grant all privileges on database <mydb> to <myuser>;
6. Zugriffe steuern:
Es gibt eine ganz unscheinbare Datei im Verzeichnis /var/lib/pgsql/data mit dem Namen pg_hba.conf. Die Abkürzung steht für PostgreSQL Host-Based Authentication Configuration und ist damit der Türsteher deines PostgreSQL-Servers. Darin wird festgelegt, wer Zugriff auf deine Datenbanken erhält und wie er sich gegebenfalls authentifzieren muss.
In der Praxis sind dafür 2 Arten besonders interessant. Die Rede ist vom lokalen Socket und dem Zugriff via TCP/IP-Verbindung. Im Folgenden findest du für die gängigsten Szenarien ein paar Beispiele. Beachte dabei aber, dass die Reihenfolge der Regeln eine große Rolle spielt. Wie bei einer Firewall, gilt auch hier, dass die erste Regel die Musik angibt. Also erst etwas erlauben, dann den Rest verbieten!
# TYPE DATABASE USER ADDRESS METHOD
## Socket ##
# Der Betriebssystem-Benutzername und der des Datenbank-Users müssen gleich lauten:
local all all peer
## Network ##
# Eine lokale Anwendung greift mithilfe des definierten Users auf die benannte Datenbank zu:
host mydb myuser localhost password
# Ein Server mit der angegebenen IP-Adresse kann sich mithilfe des festgelegten Datenbankbenutzers und dessen Passwort anmelden:
host mydb myuser 192.168.93.10/32 password
7. Datenbank-Dump erstellen:
In der Welt der Informationstechnologie ist ein zuverlässiges Sicherungskonzept unverzichtbar. Das Erstellen von PostgreSQL-Backups gestaltet sich recht unkompliziert. Zur Anfertigung von Dumps stehen sowohl pg_dumpall zur Verfügung, um alle vorhandenen Datenbanken zu sichern, als auch pg_dump, um nur einzelne Datenbanken zu archivieren.
su - postgres -c "pg_dumpall -U postgres" > backup.sql
su - postgres -c "pg_dump -U postgres -d mydb" > backup.sql
Wichtig zu wissen ist hierbei, dass beide Tools standardmäßig den lokalen Socket nutzen. Das ist bei pg_dumpall verschmerzbar, da der Super-User postgres bei der Server-Installation automatisch angelegt wird und nur er ausreichende Berechtigungen für diese Arbeiten besitzt. Bei pg_dump könnte man aber einen User angeben, der nur über die nötigen Rechte für eine Datenbank verfügt.
Standardmäßig ist der Zugriff über den lokalen Socket hier mittels der Methode peer geschützt. In so einem Fall muss der Datenbanknutzer gleichnamig auf dem lokalen System existieren. Das geht ganz einfach mithilfe von 2 Befehlen: adduser nutzer und passwd nutzer. Das erste Kommando erstellt den neuen User und der letzte Befehl vergibt noch ein Passwort.
Wenn das Anlegen des Benutzers auf Betriebssystem-Ebene nicht gewünscht ist, kann man die Authentifizierungsmethode in der pg_hba.conf auf trust herunterschrauben. Nun kann jeder lokale Nutzer mit einem Nutzernamen seiner Wahl auf den PostgreSQL-Server zugreifen. Das schließt den Super-User postgres aber natürlich auch mit ein.
Falls so ein Vorgehen keine gangbare Option ist, kann man stattdessen über eine TCP/IP-Verbindung auf die zu archivierende Datenbank zugreifen. Natürlich benötigt man hierfür wieder einen entsprechenden Eintrag. Für 127.0.0.1 existiert dieser normalerweise schon und damit sollte das folgende Kommando nach der Passwortabfrage einen Dump anfertigen:
pg_dump -h localhost -p 5432 -U myuser -d mydb > backup.sql
Es besteht noch die Möglichkeit, vorhandene Datenbanken auf Dateisystemebene zu sichern. Hierbei ist zu beachten, dass dies nur innerhalb von Major-Releases funktioniert und die Daten auf diesem Wege nicht auf neuere Systeme übernommen werden können. Alle vorhandenen Datenbanken findet man unter /var/lib/pgsql. Der Service sollte für konsistente Backups noch gestoppt werden.