15%

Zaoszczędź 15% na wszystkich usługach hostingowych

Sprawdź swoje umiejętności i zdobądź Rabat na dowolny plan hostingowy

Użyj kodu:

Skills
Rozpocznij
24.10.2024

Wyświetlanie i przełączanie baz danych w PostgreSQL: Kompletny przewodnik techniczny

PostgreSQL zarządza wieloma izolowanymi bazami danych w ramach jednej instancji serwera, z których każda ma własny schemat, role i uprawnienia. Aby wyświetlić listę wszystkich baz danych, uruchom l wewnątrz psql lub wykonaj zapytanie SELECT datname FROM pg_catalog.pg_database; z dowolnej sesji. Aby przełączyć bazę danych, musisz otworzyć nowe połączenie — PostgreSQL wymusza ścisłe powiązanie sesji z bazą danych, bez odpowiednika polecenia USE w ramach sesji.

Ten przewodnik omawia wszystkie dostępne metody wyliczania i łączenia się z bazami danych PostgreSQL, od poleceń psql i zapytań do katalogu systemowego, po ciągi połączeń, zagadnienia pg_hba.conf oraz wzorce pracy z wieloma bazami danych stosowane w środowiskach produkcyjnych.

Dlaczego przełączanie baz danych w PostgreSQL działa inaczej

Większość programistów przychodzących z MySQL spodziewa się polecenia USE database_name;. PostgreSQL celowo je pomija. Każda sesja PostgreSQL jest powiązana dokładnie z jedną bazą danych w momencie nawiązania połączenia, a to powiązanie jest niezmienne przez cały czas trwania sesji. Jest to decyzja architektoniczna zakorzeniona w modelu procesów PostgreSQL: proces backendowy (postgres) ładuje katalog systemowy bazy danych do pamięci współdzielonej podczas uruchamiania, a przełączanie katalogów w trakcie sesji i tak wymagałoby pełnego restartu procesu.

Zrozumienie tego ograniczenia z góry pozwala uniknąć godzin debugowania i kształtuje sposób projektowania narzędzi wielobazodanowych, pul połączeń i konfiguracji aplikacji.

Wyświetlanie listy wszystkich baz danych w PostgreSQL

Metoda 1: Meta-polecenie l w psql

Najszybszym sposobem wyliczenia baz danych jest meta-polecenie l (alias: list) wewnątrz interaktywnej sesji psql.

psql -U postgres

Po nawiązaniu połączenia:

l

Wynikiem jest sformatowana tabela podobna do:

                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 myapp_db  | appuser  | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 analytics | analyst  | UTF8     | en_US.UTF-8 | en_US.UTF-8 | analyst=CTc/analyst
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

Kolumny ujawniają więcej niż tylko nazwy: Encoding ma znaczenie przy migracji danych między serwerami, Collate wpływa na kolejność sortowania i zachowanie indeksów, a Access privileges używa notacji ACL PostgreSQL (C = CONNECT, T = TEMPORARY, c = CREATE).

Aby uzyskać rozszerzone szczegóły, w tym przestrzeń tabel i limity połączeń, użyj:

l+

Metoda 2: Zapytanie do katalogu systemowego pg_database

Do skryptowania, monitorowania lub introspekcji na poziomie aplikacji wykonaj zapytanie bezpośrednio do widoku pg_catalog.pg_database. Działa to z dowolnej bazy danych w klastrze, ponieważ katalogi systemowe są widoczne globalnie.

SELECT
    datname        AS database_name,
    pg_catalog.pg_get_userbyid(datdba) AS owner,
    pg_encoding_to_char(encoding) AS encoding,
    datcollate     AS collation,
    datctype       AS ctype,
    datconnlimit   AS connection_limit,
    pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(datname)) AS size
FROM pg_catalog.pg_database
WHERE datistemplate = false
ORDER BY datname;

Filtrowanie datistemplate = false wyklucza template0 i template1 z wyników — są to szablony systemowe, a nie operacyjne bazy danych. Kolumna datconnlimit jest kluczowa w środowiskach współdzielonych: wartość -1 oznacza brak limitu, podczas gdy każda dodatnia liczba całkowita ogranicza liczbę jednoczesnych połączeń z tą bazą danych.

Wskazówka produkcyjna: Dodaj pg_database_size() do zapytań monitorujących. Baza danych po cichu przekraczająca pojemność przestrzeni tabel jest częstą przyczyną błędów zapisu, które są trudne do zdiagnozowania po fakcie.

Metoda 3: Wyświetlanie listy baz danych bez wchodzenia do psql

W przypadku skryptów powłoki i potoków automatyzacji można pobrać listę baz danych bez wchodzenia do sesji interaktywnej:

psql -U postgres -c "l"

Lub dla czystych, przetwarzalnych przez skrypty danych wyjściowych:

psql -U postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;"

Flaga -t pomija nagłówki kolumn i liczby wierszy, zwracając tylko surowe wartości — idealne do przekazywania potokiem do grep, awk lub tablic Bash.

Aby wyeksportować listę do pliku:

psql -U postgres -t -A -c "SELECT datname FROM pg_database WHERE datistemplate = false;" > db_list.txt
-A wyłącza wyrównanie kolumn, generując jedną nazwę bazy danych w każdym wierszu.
Przełączanie między bazami danych w PostgreSQL
Ponieważ nie można przełączać baz danych w ramach aktywnej sesji, właściwym podejściem jest zakończenie bieżącego połączenia i nawiązanie nowego, skierowanego do żądanej bazy danych. Istnieje kilka sposobów, aby zrobić to efektywnie.
Metoda 1: Wyjście i ponowne połączenie z powłoki
Wewnątrz psql zakończ bieżącą sesję:
q
Następnie połącz się z docelową bazą danych:
psql -U postgres -d target_database
Metoda 2: Użycie c (Connect) wewnątrz psql
Jest to najbardziej praktyczna metoda do pracy interaktywnej. Meta-polecenie c zamyka bieżące połączenie i otwiera nowe do wskazanej bazy danych — wszystko w ramach tej samej sesji terminala.
c target_database
Można również jednocześnie zmienić użytkownika i hosta:
c target_database admin_user localhost 5432
Składnia: c [database [username [host [port]]]]

Po uruchomieniu c, psql wyświetli potwierdzenie:

You are now connected to database "target_database" as user "postgres".

Ważny przypadek brzegowy: Jeśli docelowa baza danych nie istnieje lub bieżący użytkownik nie ma uprawnienia CONNECT, polecenie c zakończy się niepowodzeniem i powróci do poprzedniego połączenia. Jest to bezpieczniejsze niż się wydaje — nie zostaniesz bez połączenia, ale w skryptach musisz obsłużyć ten przypadek, sprawdzając status wyjścia.

Metoda 3: Łączenie jako inny użytkownik

Aby połączyć się z bazą danych w ramach określonej roli:

psql -d myapp_db -U appuser -h localhost -p 5432

Lub używając skrótu c wewnątrz istniejącej sesji:

c myapp_db appuser

Jest to szczególnie przydatne podczas testowania polityk zabezpieczeń na poziomie wierszy (RLS) lub weryfikowania, że użytkownicy aplikacji nie mają dostępu do tabel poza swoim schematem.

Metoda 4: Używanie ciągów połączeń (format URI)

PostgreSQL obsługuje format URI połączenia libpq, który zawiera wszystkie parametry połączenia w jednym ciągu. Jest to preferowana metoda dla konfiguracji aplikacji, potoków CI/CD i narzędzi infrastruktury jako kodu.

psql "postgresql://appuser:password@localhost:5432/myapp_db"

Lub używając schematu postgres:// (oba są prawidłowe):

psql "postgres://appuser:password@db.example.com:5432/analytics?sslmode=require"

Parametr ?sslmode=require wymusza szyfrowanie TLS połączenia — jest to bezwzględny wymóg dla każdej bazy danych dostępnej spoza localhost. Jeśli hostujesz PostgreSQL na VPS lub serwerze dedykowanym, zawsze łącz ciągi połączeń z sslmode=require lub sslmode=verify-full i ważnym certyfikatem SSL.

Godne uwagi parametry URI połączenia:

ParametrPrzeznaczeniePrzykładowa wartość
sslmodePoziom wymuszania TLSrequire, verify-full
connect_timeoutSekundy przed niepowodzeniem połączenia10
application_nameIdentyfikuje klienta w pg_stat_activitymyapp_worker
optionsPrzekazuje parametry GUC po stronie serwera-c search_path=myschema

Metoda 5: Używanie psql ze zmiennymi środowiskowymi

W przypadku wielokrotnych połączeń z tym samym klastrem ustaw zmienne środowiskowe, aby uniknąć wielokrotnego wpisywania danych uwierzytelniających:

export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGPASSWORD=secret   # Use .pgpass file in production instead
export PGDATABASE=myapp_db

psql

W środowisku produkcyjnym użyj pliku .pgpass zamiast PGPASSWORD, aby uniknąć ujawniania danych uwierzytelniających w historii powłoki lub listach procesów:

# ~/.pgpass format: hostname:port:database:username:password
localhost:5432:myapp_db:appuser:strongpassword

Ustaw odpowiednie uprawnienia, w przeciwnym razie PostgreSQL zignoruje plik:

chmod 600 ~/.pgpass

Porównanie: metody przełączania baz danych

MetodaKontekstWymaga nowego procesuObsługuje zmianę użytkownikaSkryptowalność
q + psql -dPowłokaTakTakTak
c dbnamepsql interaktywnyNie (psql obsługuje to)TakOgraniczona
URI połączeniaPowłoka / AplikacjaTakTakTak
Zmienne środowiskowePowłokaTakTakTak
pgAdmin GUIKlient GUINieTakNie
Pula połączeń (PgBouncer)AplikacjaNieZależy od trybuTak

Efektywne zarządzanie wieloma połączeniami z bazami danych

Używanie pgAdmin do nawigacji opartej na GUI

pgAdmin wyświetla wszystkie bazy danych pod każdym zarejestrowanym serwerem w drzewie obiektów po lewej stronie. Kliknięcie bazy danych i otwarcie narzędzia Query Tool automatycznie ogranicza wszystkie zapytania do tej bazy danych. Jest to przydatne do pracy eksploracyjnej, ale nie nadaje się do automatyzacji.

Pułapka: pgAdmin utrzymuje oddzielne sloty połączeń dla każdej bazy danych. Jeśli serwer PostgreSQL ma niskie ustawienie max_connections (domyślnie 100), otwieranie wielu baz danych w pgAdmin może wyczerpać pulę połączeń, zanim aplikacja w ogóle się uruchomi.

Używanie PgBouncer do puli połączeń

W środowiskach produkcyjnych z częstym przełączaniem baz danych, pula połączeń taka jak PgBouncer znacznie redukuje narzut. PgBouncer działa w trzech trybach:

  • Tryb sesji: Jedno połączenie serwera na sesję klienta. Funkcjonalnie równoważny bezpośrednim połączeniom.
  • Tryb transakcji: Połączenie serwera jest utrzymywane tylko podczas transakcji. Najbardziej wydajny dla obciążeń OLTP.
  • Tryb instrukcji: Połączenie zwracane po każdej instrukcji. Niekompatybilny z transakcjami wieloinstrukcyjnymi.

Przy uruchamianiu wielu baz danych aplikacji na jednej instancji PostgreSQL — co jest powszechnym wzorcem na hostingu VPS lub VPS z cPanel — PgBouncer w trybie transakcji może zmniejszyć liczbę aktywnych procesów backendowych o rząd wielkości.

Ponieważ sesje są ograniczone do bazy danych, zapytania o dane między bazami danych wymagają rozszerzenia. PostgreSQL oferuje dwie opcje:

dblink — starsze, proceduralne podejście:

SELECT * FROM dblink(
    'dbname=analytics user=analyst host=localhost',
    'SELECT user_id, event_count FROM events WHERE date = current_date'
) AS remote(user_id INT, event_count BIGINT);

postgres_fdw — nowoczesny, zgodny ze standardami Foreign Data Wrapper:

CREATE EXTENSION postgres_fdw;

CREATE SERVER analytics_server
    FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host 'localhost', dbname 'analytics', port '5432');

CREATE USER MAPPING FOR appuser
    SERVER analytics_server
    OPTIONS (user 'analyst', password 'secret');

CREATE FOREIGN TABLE remote_events (
    user_id INT,
    event_count BIGINT
)
SERVER analytics_server
OPTIONS (schema_name 'public', table_name 'events');

Po konfiguracji remote_events zachowuje się jak tabela lokalna. postgres_fdw obsługuje pushdown predykatów, co oznacza, że klauzule WHERE są wykonywane na serwerze zdalnym, a nie lokalnie — kluczowe rozróżnienie wydajnościowe dla dużych zbiorów danych.

Systemowe bazy danych: czego nie wolno dotykać

PostgreSQL dostarcza cztery bazy danych w każdym nowym klastrze:

Baza danychPrzeznaczenieBezpieczne do połączenia?Bezpieczne do modyfikacji?
postgresDomyślna baza danych administratoraTakZ ostrożnością
template1Szablon dla CREATE DATABASETakTak, zmiany są propagowane
template0Czysty bazowy szablonRzadkoNie
pg_catalogNie jest bazą danych, lecz schematemN/DNigdy

template1 jest klonowany za każdym razem, gdy uruchamiasz CREATE DATABASE bez podania szablonu. Jeśli instalujesz rozszerzenia lub tworzysz schematy w template1, każda nowa baza danych je dziedziczy. Jest to przydatne do standaryzacji środowisk, ale niebezpieczne, jeśli zrobione przypadkowo.

template0 istnieje jako nieskazitelny punkt awaryjny. Jest to jedyny szablon, który można użyć podczas przywracania archiwum pg_dump z innym kodowaniem lub ustawieniami regionalnymi, ponieważ nie zawiera obiektów tworzonych przez użytkownika, które mogłyby powodować konflikty.

Uprawnienia, pg_hba.conf i błędy połączeń

Częstym źródłem zamieszania przy przełączaniu baz danych jest rozróżnienie między uprawnieniami na poziomie roli PostgreSQL a regułami uwierzytelniania pg_hba.conf. Oba muszą niezależnie zezwalać na połączenie.

Sprawdzenie na poziomie roli: Rola musi mieć uprawnienie CONNECT do docelowej bazy danych:

GRANT CONNECT ON DATABASE target_database TO appuser;

Sprawdzenie pg_hba.conf: Plik uwierzytelniania opartego na hoście (/etc/postgresql/15/main/pg_hba.conf w Debian/Ubuntu) musi zawierać pasującą regułę dla użytkownika, bazy danych i adresu źródłowego. Typowy wpis:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    myapp_db        appuser         10.0.0.0/8              scram-sha-256

Po edycji pg_hba.conf przeładuj konfigurację bez restartu serwera:

sudo systemctl reload postgresql

Lub z poziomu psql:

SELECT pg_reload_conf();

Typowy wzorzec błędu: Użytkownik ma uprawnienie CONNECT na poziomie SQL, ale pg_hba.conf nie ma pasującej reguły. Komunikat o błędzie (FATAL: no pg_hba.conf entry for host) jest jednoznaczny, ale programiści często całkowicie pomijają ten plik, ponieważ oczekują, że uprawnienia do bazy danych będą zarządzane wyłącznie przez SQL.

Praktyczna macierz decyzyjna

Użyj tej listy kontrolnej, aby wybrać właściwe podejście do połączenia dla swojego scenariusza:

  • Interaktywna eksploracja na lokalnej maszynie deweloperskiej: Użyj c dbname wewnątrz psql. Szybkie, bez nowego procesu.
  • Skrypt powłoki iterujący po wielu bazach danych: Użyj psql -U postgres -d $dbname -c "..." w pętli z -t -A dla czystych danych wyjściowych.
  • Aplikacja łącząca się z jedną bazą danych: Użyj URI połączenia z sslmode=require i pulą połączeń (PgBouncer lub wbudowane poolowanie sterownika).
  • Aplikacja potrzebująca danych z dwóch baz danych: Zaimplementuj postgres_fdw na głównej bazie danych zamiast zarządzać dwiema oddzielnymi pulami połączeń w kodzie aplikacji.
  • Weryfikacja RLS lub izolacji uprawnień: Użyj c dbname role_name, aby podszyć się pod docelową rolę bez opuszczania psql.
  • Automatyczne provisionowanie / infrastruktura jako kod: Użyj zmiennych środowiskowych lub .pgpass z kontem serwisowym; nigdy nie umieszczaj danych uwierzytelniających na stałe w skryptach.
  • Produkcyjne obciążenie o wysokiej współbieżności: Wdróż PgBouncer w trybie transakcji między aplikacją a PostgreSQL. Na serwerze dedykowanym dostosuj max_connections w postgresql.conf do pojemności pamięci sprzętu (każdy backend używa około 5–10 MB RAM).
  • SaaS wielodostępny z bazami danych per tenant: Rozważ wielodostępność opartą na schematach w ramach jednej bazy danych zamiast baz danych per tenant, aby uniknąć fragmentacji puli połączeń i uprościć strategie tworzenia kopii zapasowych.

Dla zespołów uruchamiających PostgreSQL razem z aplikacjami webowymi, połączenie serwera bazy danych z odpowiednio skonfigurowanym środowiskiem hostingu współdzielonego lub VPS oraz zarejestrowaną domeną dla warstwy aplikacji uzupełnia standardowy stos produkcyjny.

FAQ

Czy mogę przełączyć bazę danych bez zamykania sesji psql?

Tak. Użyj meta-polecenia c target_database wewnątrz psql. Zamyka ono bieżące połączenie backendowe i otwiera nowe do wskazanej bazy danych, wszystko w ramach tej samej sesji terminala. Opcjonalnie możesz podać innego użytkownika, hosta i port w tym samym poleceniu.

Dlaczego PostgreSQL nie ma polecenia USE jak MySQL?

Architektura PostgreSQL wiąże proces backendowy z jedną bazą danych podczas uruchamiania. Katalog systemowy bazy danych jest ładowany do pamięci współdzielonej dla tego procesu, a przełączanie katalogów w trakcie sesji jest architektonicznie równoważne uruchomieniu nowego procesu. Polecenie c w psql jest praktycznym odpowiednikiem — po prostu sprawia, że restart procesu jest przezroczysty dla użytkownika.

Jak wykonywać zapytania o dane z dwóch różnych baz danych PostgreSQL jednocześnie?

Użyj rozszerzenia postgres_fdw, aby utworzyć serwer zewnętrzny i tabele zewnętrzne mapowane na zdalną bazę danych. Po konfiguracji możesz łączyć tabele lokalne i zdalne w jednym zapytaniu za pomocą JOIN. Do jednorazowych zapytań dblink jest prostszy, ale mniej wydajny i trudniejszy w utrzymaniu.

Co się stanie, jeśli połączę się z template1 i ją zmodyfikuję?

Wszelkie obiekty tworzone w template1 — tabele, rozszerzenia, schematy — zostaną sklonowane do każdej nowej bazy danych utworzonej za pomocą CREATE DATABASE (chyba że TEMPLATE template0 zostanie jawnie podany). Jest to czasami zamierzone (np. wstępna instalacja uuid-ossp lub pgcrypto), ale przypadkowe modyfikacje mogą uszkodzić wszystkie następnie tworzone bazy danych.

Jak sprawdzić, z którą bazą danych jest połączona bieżąca sesja psql?

Uruchom następujące polecenie wewnątrz psql:

SELECT current_database();

Lub sprawdź sam monit psql — domyślnie wyświetla dbname=# (superużytkownik) lub dbname=> (zwykły użytkownik), gdzie dbname to aktywna baza danych.

15%

Zaoszczędź 15% na wszystkich usługach hostingowych

Sprawdź swoje umiejętności i zdobądź Rabat na dowolny plan hostingowy

Użyj kodu:

Skills
Rozpocznij