Instalacja MySQL to jedno polecenie. Większość pracy zaczyna się potem: użytkownik dla aplikacji, sposób na dostęp do bazy z własnego komputera bez wystawiania portu 3306 do internetu, ustawienia pamięci dla małego serwera i kopie zapasowe, które robią się bez ciebie. Ten poradnik obejmuje wszystkie cztery na Ubuntu 24.04. Każdy krok wykonaliśmy na naszym obrazie Ubuntu 24.04, a poniższe liczby pochodzą z tego serwera.
Wykonuj polecenia jako użytkownik z sudo. Tworzy go poradnik konfiguracji Ubuntu.
1. Zainstaluj
sudo apt update
sudo apt install -y mysql-server
mysql --version
Na naszym serwerze instalacja trwała 51 sekund i dała MySQL 8.0.46. Uruchamia się od razu, startuje przy każdym uruchomieniu systemu i nasłuchuje tylko na samym serwerze: 127.0.0.1:3306 dla zwykłych połączeń i 127.0.0.1:33060 dla nowszego protokołu X. Z zewnątrz nic jeszcze nie jest dostępne.
2. Utwórz bazę i użytkownika
Konto root w MySQL używa w Ubuntu uwierzytelniania przez gniazdo, więc sudo mysql loguje cię bez hasła. Utwórz bazę i użytkownika dla aplikacji:
sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;
Sprawdź to tak, jak będzie łączyć się aplikacja:
mysql -u app -p app -e "SELECT CURRENT_USER();"
Powinno wypisać app@localhost. Złe hasło kończy się ERROR 1045 (28000): Access denied for user 'app'@'localhost'. Użytkownik może wszystko wewnątrz app i nic poza nią.
3. Połączenie z własnego komputera: tunel SSH
Aby używać klienta desktopowego, takiego jak DBeaver, MySQL Workbench czy konsolowy mysql na swoim komputerze, nie otwieraj portu. Przekieruj go przez SSH:
ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP
Na planie z NAT dodaj -p i osobisty port SSH z panelu. Dopóki to okno jest otwarte, skieruj klienta na host 127.0.0.1, port 3307, użytkownik app. Po stronie lokalnej użyliśmy 3307, żeby nie kolidować z MySQL, który może działać na twoim komputerze. W naszym teście serwer od razu odpowiedział przez tunel, a bezpośrednie połączenie z jego adresem na 3306 zostało odrzucone.
4. Bezpośredni dostęp dla jednego innego serwera
Czasem aplikacja działa na drugim serwerze i musi łączyć się bezpośrednio. Baza potrzebuje wtedy planu z własnym IPv4, bo plan z NAT przekierowuje tylko twój port SSH. Trzy zmiany, wszystkie ograniczone do adresu serwera aplikacji (tu 203.0.113.20):
sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';
Jeśli ufw nie jest jeszcze włączony, najpierw dopuść SSH (sudo ufw allow OpenSSH), a potem uruchom sudo ufw enable. Szczegóły są w poradniku ufw.
Sprawdziliśmy oba zamki osobno. Z regułą w zaporze, ale bez pasującego użytkownika MySQL, serwer odmówił z error 1130: Host '…' is not allowed to connect to this MySQL server. Po dodaniu użytkownika połączenie przeszło. Bez reguły w zaporze połączenie po prostu kończyło się przekroczeniem czasu. Każdy inny adres w internecie dostaje to samo przekroczenie czasu.
5. Mniej RAM
W spoczynku, bez własnych danych, MySQL 8.0 zajmował na naszym serwerze 383 MB. Większość to Performance Schema, funkcja diagnostyczna rezerwująca pamięć z góry. Na małym VPS wyłącz ją i sam ustaw rozmiar głównej pamięci podręcznej:
sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld
Po restarcie zajmował 165 MB. Buffer pool przechowuje w pamięci dane i indeksy, a 256 MB pasuje do serwera z 2 GB, na którym działa też aplikacja. Zwiększ go, jeśli baza jest najważniejszą rzeczą na serwerze i urosła ponad rozmiar cache. max_connections = 50 w zupełności wystarcza jednej aplikacji z pulą połączeń. Tracisz statystyki performance_schema. Włącz je z powrotem, jeśli kiedyś trzeba będzie dokładnie zbadać wolne zapytania.
6. Nocne kopie zapasowe
mysqldump --single-transaction robi spójną kopię tabel InnoDB bez blokowania aplikacji. Zamknij to w małym skrypcie:
sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql
Każdy wiersz ma swój powód:
umask 077sprawia, że zrzut może czytać tylko root (-rw-------), bo zawiera wszystkie twoje dane.pipefailsprawia, że cały skrypt kończy się błędem, gdy zawiedziemysqldump. Bez tegogzipzapisałby maleńkie puste archiwum i zgłosił sukces. Celowo zepsuliśmy polecenie i skrypt zakończył się kodem 2, tak jak powinien.find … -mtime +14 -deletetrzyma kopie z dwóch tygodni.- Skrypt działa jako root, więc
mysqldumploguje się przez gniazdo i hasło nie leży w żadnym pliku.
Kopia, której nigdy nie odtworzyłeś, jeszcze się nie liczy. Odtwórz ją do tymczasowej bazy i obejrzyj dane:
sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"
W naszym teście odtworzona tabela miała te same wiersze co oryginał. Kopie na tym samym dysku nie chronią przed utratą serwera, więc co jakiś czas przenoś je na inną maszynę przez scp albo restic. Managed Backups dokładają do tego codzienne punkty przywracania całego serwera.
Jaki plan
Micro (2 vCPU, 2 GB, 25 GB, $5/mies.) utrzyma MySQL z takim strojeniem plus aplikację webową. Jeśli sama baza urośnie powyżej kilku gigabajtów, Small z 4 GB i 35 GB za $8/mies. pozwoli dać buffer poolowi 1 GB lub więcej. Oba plany są z NAT, a tunel SSH z kroku 3 na nich działa. Krok 4 wymaga własnego IPv4: Micro-IP kosztuje $10/mies.
Wolisz PostgreSQL? Poradnik PostgreSQL ma ten sam plan. Wszystkie plany są w dziale VPS, a płatność w USDT, USDC lub ETH w sieciach Base, Ethereum lub Polygon.
Komentarze
Brak komentarzy. Bądź pierwszy.