1.  [Strona główna](/) ›
2.  [Baza wiedzy](/baza-wiedzy/) ›
3.  MySQLTuner - optymalizacja MySQL

# MySQLTuner - optymalizacja MySQL i MariaDB na VPS

Opublikowano: 10 kwietnia 2026 · Kategoria: VPS / Bazy danych

⚡ W skrócie · 12 min czytania

-   Jak używać MySQLTuner do optymalizacji MySQL: interpretacja raportu, innodb\_buffer\_pool\_size, max\_connections, query\_cache, thread\_cache\_size. SHOW VARIABLES vs SHOW STATUS.
-   Pobranie i uruchomienie MySQLTuner.
-   Instalacja z pakietu (apt, dnf) lub z GitHuba, uruchomienie zdalne, w Dockerze i na Windowsie.
-   Najczęstsze ostrzeżenia \[!!\] i bezpieczne wdrażanie rekomendacji.
-   Interpretacja raportu - sekcje wyjścia.
-   Kluczowe parametry i ich optymalizacja.
-   SHOW VARIABLES vs SHOW STATUS - diagnostyka.

Domyślna konfiguracja MySQL jest celowo ostrożna - zaprojektowana do działania na serwerach z minimalną pamięcią i nie wykorzystuje zasobów, które masz na VPS. Wynikiem są wolne zapytania, zbyt mało połączeń i nadmierne odczyty z dysku zamiast z RAM. MySQLTuner to narzędzie, które analizuje Twój serwer i mówi wprost co zmienić i dlaczego. Artykuł pokazuje jak interpretować raport i implementować rekomendacje.

## Pobranie i uruchomienie MySQLTuner

```
# Pobierz najnowszą wersję MySQLTuner
wget http://mysqltuner.pl/ -O mysqltuner.pl
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/basic_passwords.txt -O basic_passwords.txt
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/vulnerabilities.csv -O vulnerabilities.csv

# Uruchomienie (jako root lub uzytkownik z pelnym dostepem)
perl mysqltuner.pl --user root --pass "TwojHaslo"

# Lub z pliku .my.cnf (bezpieczniejsze)
# [client]
# user=root
# password=TwojHaslo
# plik: ~/.my.cnf (chmod 600)
perl mysqltuner.pl

# Opcje zaawansowane
perl mysqltuner.pl \
  --buffers        \  # szczegoly buforow
  --idxstats       \  # statystyki indeksow
  --dbstat         \  # statystyki baz
  --outputfile /tmp/mysqltuner-report.txt   # zapis do pliku
```

## Instalacja MySQLTuner z repozytorium pakietów lub z GitHuba

MySQLTuner to pojedynczy skrypt Perl, więc nie trzeba go instalować: wystarczy pobrać plik `mysqltuner.pl` jak wyżej. Jeśli wolisz mieć go jako pakiet systemowy (aktualizacje razem z resztą systemu), jest dostępny w repozytoriach Debiana i Ubuntu oraz w EPEL dla AlmaLinux i Rocky Linux. Wersja z repozytorium bywa starsza niż ta z GitHuba, a starsze wersje gorzej rozpoznają nowe wydania MySQL i MariaDB, dlatego przy nowym serwerze bazy lepiej uruchomić najnowszy skrypt.

```
# Debian / Ubuntu
sudo apt update && sudo apt install mysqltuner
sudo mysqltuner

# AlmaLinux / Rocky Linux (repozytorium EPEL)
sudo dnf install epel-release
sudo dnf install mysqltuner

# Najnowsza wersja prosto z GitHuba (MySQLTuner download)
git clone --depth 1 https://github.com/major/MySQLTuner-perl.git
cd MySQLTuner-perl
perl mysqltuner.pl --user root --pass "TwojHaslo"

# Wymagania: interpreter Perl (jest w praktycznie każdej dystrybucji Linuksa)
perl -v
```

## MySQLTuner online, w Dockerze i na Windowsie

**MySQLTuner online.** Oficjalny projekt nie ma wersji online. Skrypt musi połączyć się z serwerem bazy i odczytać jego zmienne oraz liczniki, więc uruchamiasz go na serwerze albo na maszynie, która ma dostęp do bazy przez sieć. Serwisy "online", do których wkleja się wynik `SHOW GLOBAL STATUS` i `SHOW GLOBAL VARIABLES`, dostają pełny obraz konfiguracji Twojej bazy, dlatego na produkcji bezpieczniej użyć lokalnego skryptu.

**Połączenie zdalne.** Gdy uruchamiasz MySQLTuner na innej maszynie niż baza, skrypt nie widzi pamięci RAM ani swapu serwera bazy. Trzeba je podać ręcznie przez `--forcemem` i `--forceswap` (w MB), inaczej rekomendacje dotyczące buforów będą policzone dla złej maszyny.

**MySQLTuner w Dockerze.** Najprostsza droga to uruchomienie skryptu na hoście i połączenie z kontenerem przez opublikowany port. Jako `--forcemem` podaj limit pamięci kontenera (a nie RAM całego hosta), bo to on wyznacza, ile może zająć bufor InnoDB. Użyj adresu `127.0.0.1`, a nie `localhost`: klient MySQL przy `localhost` próbuje połączyć się przez gniazdo uniksowe, którego na hoście nie ma.

```
# Baza na innym serwerze (VPS 4 GB RAM, 1 GB swap)
perl mysqltuner.pl --host 10.0.0.5 --port 3306 \
  --user tuner --pass "TwojHaslo" \
  --forcemem 4096 --forceswap 1024

# Baza w kontenerze z portem 3306 opublikowanym na hoście
docker inspect --format '{{.HostConfig.Memory}}' nazwa_kontenera   # limit w bajtach, 0 = brak limitu
perl mysqltuner.pl --host 127.0.0.1 --port 3306 \
  --user root --pass "TwojHaslo" --forcemem 2048
```

**MySQLTuner na Windowsie.** Skrypt jest pisany pod Linuksa i Uniksa (część danych o systemie czyta z narzędzi systemowych), więc na Windowsie najwygodniej uruchomić go w WSL albo z dowolnej maszyny z Linuksem, łącząc się z bazą zdalnie z parametrem `--forcemem`.

## Interpretacja raportu - sekcje wyjścia

MySQLTuner dzieli raport na sekcje. Kluczowe linie to te z `[!!]` (ostrzeżenie) i `[OK]` (w porządku). Na końcu sekcja **Recommendations** zbiera konkretne zmiany do zastosowania.

```
-------- General Statistics --------
[--] Skipped version check for MySQLTuner script
[OK]  Currently running supported MySQL version 8.0.36-MySQL

-------- Storage Engine Statistics --------
[OK]  InnoDB is enabled
[!!]  InnoDB buffer pool / data size: 128.0M/4.5G       # KLUCZOWE!
[!!]  InnoDB buffer pool instances: 1 (recommended: 4+)
[OK]  InnoDB Read buffer efficiency: 94.28%              # powinno byc >99%

-------- Performance Metrics --------
[!!]  Slow queries: 2% (1K/52K)                         # powyzej 1% = problem
[OK]  Highest connection usage: 42% of max_connections
[!!]  Threads created per second: 12 (should be < 5)    # thread cache za maly
[OK]  Table cache hit rate: 91%

-------- Recommendations --------
General recommendations:
  Add skip-name-resolve to my.cnf
  innodb_buffer_pool_size (>= 3G)
  innodb_buffer_pool_instances = 4
  thread_cache_size = 50
  slow_query_log = 1
```

### Najczęstsze ostrzeżenia \[!!\] i co z nimi zrobić

Ostrzeżenie w raporcie

Co oznacza

Co zrobić

Maximum possible memory usage

Przy komplecie połączeń bufory per połączenie mogą przekroczyć RAM

Obniż `max_connections` do realnego szczytu albo zmniejsz bufory per połączenie (`sort_buffer_size`, `join_buffer_size`)

Joins performed without indexes

Zapytania łączą tabele bez indeksu na kolumnie złączenia

Znajdź je w slow query log i dodaj indeksy; podnoszenie `join_buffer_size` tylko maskuje problem

Temporary tables created on disk

Tabele tymczasowe nie mieszczą się w pamięci

Podnieś razem `tmp_table_size` i `max_heap_table_size`; kolumny TEXT/BLOB w wyniku i tak trafią na dysk, wtedy pomaga zmiana zapytania

Key buffer used / MyISAM

Część tabel nadal używa silnika MyISAM

Zamień tabele na InnoDB (`ALTER TABLE ... ENGINE=InnoDB`, po kopii zapasowej), wtedy `key_buffer_size` można zmniejszyć

Aborted connections

Klienci zrywają połączenia albo podają złe hasło

Sprawdź log błędów, timeouty aplikacji i próby logowania z zewnątrz; baza nie powinna nasłuchiwać publicznie

Name resolution is active

Każde połączenie wymaga odpytania DNS

Dodaj `skip-name-resolve` i nadawaj uprawnienia po adresach IP, nie nazwach hostów

## Kluczowe parametry i ich optymalizacja

Parametr

Domyślna wartość

Rekomendacja (VPS 8 GB)

Efekt

`innodb_buffer_pool_size`

128 MB

4-6 GB (70% RAM)

Więcej danych w RAM, mniej I/O dysku

`innodb_buffer_pool_instances`

1

4-8 (1 per GB pool)

Mniejszy contention na mutex pool

`max_connections`

151

300-500

Więcej równoczesnych połączeń

`thread_cache_size`

9

50-100

Mniej tworzenia nowych wątków (CPU)

`query_cache_type`

0 (OFF) w MySQL 5.7 i MariaDB 10.1.7+

0 (OFF, read-heavy: 1)

Brak mutex contention przy write-heavy

`innodb_log_file_size`

48 MB

256-512 MB

Mniej checkpoint flushes, lepszy write perf

`tmp_table_size / max_heap_table_size`

16 MB

64-256 MB

Mniej temporary tables na dysku

```
# /etc/mysql/mysql.conf.d/mysqld.cnf - przykład dla VPS 8 GB RAM

# [mysqld]
# --- InnoDB ---
# innodb_buffer_pool_size = 4G
# innodb_buffer_pool_instances = 4
# innodb_log_file_size = 256M
# innodb_flush_log_at_trx_commit = 2    # 1=bezpieczne, 2=szybsze (ryzyko utraty 1s transakcji)
# innodb_flush_method = O_DIRECT
#
# --- Polaczenia ---
# max_connections = 300
# thread_cache_size = 50
# wait_timeout = 300
# interactive_timeout = 300
#
# --- Tymczasowe tabele ---
# tmp_table_size = 128M
# max_heap_table_size = 128M
#
# --- Query cache (MySQL 5.7 - dla MySQL 8.0 usun) ---
# query_cache_type = 0
# query_cache_size = 0
#
# --- Slow query log ---
# slow_query_log = 1
# slow_query_log_file = /var/log/mysql/slow.log
# long_query_time = 1
# log_queries_not_using_indexes = 1
#
# --- Siec ---
# skip-name-resolve
# bind-address = 127.0.0.1

# Zastosuj bez restartu (czesciowo)
mysql -u root -p -e "SET GLOBAL innodb_buffer_pool_size = 4*1024*1024*1024;"
mysql -u root -p -e "SET GLOBAL max_connections = 300;"

# Pelny restart (dla innodb_log_file_size wymagany)
sudo systemctl restart mysql
```

### Nowsze wersje: MySQL 8.0.30+ i MariaDB 10.5+

Część parametrów z przykładu wyżej zmieniła się w nowszych wydaniach i stara konfiguracja przeniesiona 1:1 może dać ostrzeżenia w logu albo zostać po cichu zignorowana:

-   **MySQL 8.0.30 i nowsze:** rozmiar dziennika redo ustawia `innodb_redo_log_capacity`, a `innodb_log_file_size` i `innodb_log_files_in_group` są przestarzałe. Na nowej instalacji ustawiaj jeden parametr, np. `innodb_redo_log_capacity = 512M`.
-   **MySQL 8.0:** query cache nie istnieje, więc wpisy `query_cache_*` w my.cnf powodują błąd startu serwera. Usuń je przed aktualizacją z 5.7.
-   **MariaDB 10.5 i nowsze:** InnoDB używa jednej instancji puli buforów, a `innodb_buffer_pool_instances` jest przestarzały (w 10.6 usunięty), więc rekomendacja "4+ instancje" ze starszych wersji MySQLTuner nie ma tu zastosowania.

## SHOW VARIABLES vs SHOW STATUS - diagnostyka

```
# SHOW VARIABLES - aktualna konfiguracja
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL VARIABLES LIKE '%cache%';

# SHOW STATUS - statystyki runtime (od ostatniego restartu)
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
-- Innodb_buffer_pool_read_requests  = total reads tried from buffer
-- Innodb_buffer_pool_reads          = reads that needed disk I/O
-- Ratio hit: 1 - (Reads / Read_requests) powinno byc >99%

SHOW GLOBAL STATUS LIKE 'Threads%';
-- Threads_created    = ile watkow bylo tworzonych (powinno byc niskie)
-- Threads_running    = aktualnie aktywne watki

SHOW GLOBAL STATUS LIKE 'Slow_queries';
SHOW GLOBAL STATUS LIKE 'Questions';   -- total queries

SHOW GLOBAL STATUS LIKE 'Qcache%';
-- Qcache_hits / (Qcache_hits + Qcache_inserts) = skutecznosc query cache

-- Uzyteczne widoki diagnostyczne (MySQL 8.0+ / MariaDB)
SELECT * FROM sys.statement_analysis LIMIT 10;        -- top slow queries
SELECT * FROM sys.user_summary;                       -- aktywnosc per user
SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS;
```

## Weryfikacja po zmianach

```
# Zresetuj statystyki statusu
FLUSH STATUS;

# Poczekaj 24h, potem sprawdz skutecznosc bufora
SELECT
  (1 - (
    variable_value / (
      SELECT variable_value
      FROM information_schema.GLOBAL_STATUS
      WHERE variable_name = 'Innodb_buffer_pool_read_requests'
    )
  )) * 100 AS buffer_hit_ratio_pct
FROM information_schema.GLOBAL_STATUS
WHERE variable_name = 'Innodb_buffer_pool_reads';
-- Cel: > 99%

# Uruchom MySQLTuner po 24-48h i porownaj z poprzednim raportem
perl mysqltuner.pl >> /tmp/after-tuning.txt

# Sprawdz slow query log
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# -s t  = sortuj po query_time
# -t 10 = top 10
```

## Jak bezpiecznie stosować rekomendacje MySQLTuner

MySQLTuner liczy rekomendacje z liczników od ostatniego restartu i nie zna Twojej aplikacji. Dlatego jego wynik to lista hipotez do sprawdzenia, a nie gotowy my.cnf. Kilka zasad, które oszczędzają nocnych restartów:

-   **Uruchamiaj po co najmniej 24 h normalnego ruchu.** Raport zaraz po restarcie bazy opiera się na kilku minutach statystyk i potrafi zalecić odwrotne zmiany niż raport z pełnej doby.
-   **Zmieniaj jeden parametr naraz.** Po zmianie odczekaj kolejną dobę i porównaj raporty (`--outputfile` z datą w nazwie). Przy kilku zmianach jednocześnie nie wiadomo, która pomogła, a która zaszkodziła.
-   **Pilnuj sumy pamięci.** Bufory per połączenie mnożą się przez liczbę połączeń. Podniesienie `max_connections` i `sort_buffer_size` naraz może przy szczycie ruchu skończyć się zabiciem procesu bazy przez OOM killer.
-   **Zrób kopię my.cnf przed edycją** i sprawdź składnię przed restartem (`mysqld --validate-config` w MySQL 8.0.16+), żeby literówka nie zatrzymała bazy.
-   **Na hostingu współdzielonym nie dostosujesz serwera.** Konfigurację MySQL ustawia tam dostawca. MySQLTuner ma sens na własnym VPS lub serwerze dedykowanym; na współdzielonym zostaje optymalizacja zapytań i indeksów.

Gotowe ustawienia my.cnf dla VPS 2 GB i 4 GB RAM (innodb\_buffer\_pool\_size, max\_connections, tmp\_table\_size) znajdziesz w artykule [MySQL - optymalizacja i konfiguracja my.cnf](/baza-wiedzy/mysql-optymalizacja-konfiguracja/).

## Najczęstsze pytania

Co to jest MySQLTuner i jak go uruchomić? +

MySQLTuner to skrypt Perl analizujący konfigurację i statystyki runtime MySQL/MariaDB. Pobiera dane z SHOW VARIABLES i SHOW STATUS, porównuje z best practices i generuje listę rekomendacji z priorytetami. Uruchamiasz go: wget http://mysqltuner.pl/ -O mysqltuner.pl && perl mysqltuner.pl --user root --pass HASLO. Zalecane uruchamianie po minimum 24 godzinach działania serwera - wtedy statystyki są reprezentatywne. Nie wymaga instalacji, działa na żywym serwerze.

Jak dobrać wartość innodb\_buffer\_pool\_size? +

innodb\_buffer\_pool\_size to najważniejszy parametr InnoDB - im większy, tym więcej danych trzymanych w RAM zamiast czytanych z dysku. Reguła: dla dedykowanego serwera MySQL ustaw 70-80% dostępnego RAM. Dla shared hostingu (MySQL współdzieli serwer z Apache/PHP) - 25-50%. Sprawdź: SHOW GLOBAL STATUS LIKE "Innodb\_buffer\_pool\_read\_requests" i "Innodb\_buffer\_pool\_reads" - ratio powinien wynosić ponad 99% (mniej niż 1% trafień wymaga dysku).

Czym różni się SHOW VARIABLES od SHOW STATUS? +

SHOW VARIABLES pokazuje bieżącą konfigurację - wartości parametrów z my.cnf (innodb\_buffer\_pool\_size, max\_connections, query\_cache\_size). Są statyczne lub semi-statyczne (część można zmienić przez SET GLOBAL). SHOW STATUS pokazuje statystyki runtime - liczniki od ostatniego restartu (Connections, Queries, Threads\_running, Innodb\_buffer\_pool\_reads). Łącząc oba otrzymujesz pełny obraz: konfigurację + efektywność jej działania.

Kiedy wyłączyć query\_cache w MySQL? +

Query cache (query\_cache\_type) warto wyłączyć gdy masz dużo zapisów (INSERT/UPDATE/DELETE) - każdy zapis do tabeli unieważnia wszystkie zapytania dla tej tabeli w cache, generując mutex contention. Dla write-heavy baz query cache pogarsza wydajność. MySQL 8.0 całkowicie usunął query cache. Dla MariaDB: ustaw query\_cache\_type=0 query\_cache\_size=0 jeśli Qcache\_lowmem\_prunes jest wysokie lub Qcache\_hits / (Qcache\_hits + Qcache\_inserts) jest poniżej 20%.

Czy jest MySQLTuner online? +

Oficjalny MySQLTuner nie ma wersji online. To skrypt Perl, który musi połączyć się z bazą, więc uruchamiasz go na serwerze albo na maszynie z dostępem sieciowym do bazy (parametry --host i --port, a RAM serwera bazy podajesz przez --forcemem w MB). Wklejanie wyników SHOW GLOBAL STATUS i SHOW GLOBAL VARIABLES do zewnętrznych serwisów ujawnia konfigurację bazy, dlatego na produkcji lepiej użyć lokalnego skryptu.

Skąd pobrać MySQLTuner? +

Najnowszą wersję pobierzesz z GitHuba projektu (git clone https://github.com/major/MySQLTuner-perl.git) albo jednym poleceniem: wget http://mysqltuner.pl/ -O mysqltuner.pl. Jest też pakiet mysqltuner w repozytoriach Debiana i Ubuntu (apt install mysqltuner) oraz w EPEL dla AlmaLinux i Rocky Linux. Wersja z repozytorium bywa starsza, więc dla nowych wydań MySQL i MariaDB lepiej użyć skryptu z GitHuba.

Jak uruchomić MySQLTuner dla bazy w Dockerze? +

Uruchom skrypt na hoście i połącz się z kontenerem przez opublikowany port: perl mysqltuner.pl --host 127.0.0.1 --port 3306 --user root --pass HASLO --forcemem 2048. Jako --forcemem podaj limit pamięci kontenera w MB, a nie RAM całego hosta. Adres 127.0.0.1 zamiast localhost wymusza połączenie TCP, bo localhost oznacza dla klienta MySQL gniazdo uniksowe.

## Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.

Contabo

VPS z dużym RAM - więcej bufora InnoDB, mniej odczytów z dysku

MySQL Tuning

[Aktywuj rabat →](/out/contabo/#reklama "Contabo")

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/contabo/)

Mikr.us

Tani VPS do testowania konfiguracji MySQL przed produkcją

Dev/Test

[Aktywuj rabat →](/out/mikrus/#reklama "Mikr.us")

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/mikrus/)

Zenbox

Hosting z zarządzanym MySQL - bez ręcznego tuningu

Managed MySQL

[Aktywuj rabat →](/out/zenbox/#reklama "Zenbox")

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/zenbox/)

## Powiązane strony

-   [MySQL slow query log - diagnostyka wolnych zapytań](/baza-wiedzy/mysql-slow-query-log/)
-   [MySQL Replication - konfiguracja master-slave](/baza-wiedzy/mysql-replication-master-slave/)
-   [MariaDB vs MySQL - różnice i migracja](/baza-wiedzy/mariadb-vs-mysql-hosting/)
-   [Bezpieczeństwo VPS - checklist](/baza-wiedzy/bezpieczenstwo-vps-checklist/)
-   [Wszystkie artykuły](/baza-wiedzy/)
-   [Nextcloud na VPS - instalacja i konfiguracja z Nginx
    
    Nextcloud VPS: Nginx + PHP-FPM 8.2 + MariaDB + Redis, konfiguracja nginx.conf z CalDAV/CardDAV, Redis session cache…
    
    ](/baza-wiedzy/nextcloud-konfiguracja-vps/)
-   [MySQL Galera Cluster - multi-master replikacja MariaDB
    
    Galera Cluster: konfiguracja 3-węzłowego klastra MariaDB, wsrep, SST/IST, bootstrapping, split-brain, monitoring i…
    
    ](/baza-wiedzy/mysql-galera-cluster/)
-   [Jaki VPS wybrać?](/jaki-vps-wybrac/)

Autor: [Redakcja HostGrade.pl](/autorzy/) Zespół redakcyjny · Aktualizacja: 7 października 2026

Artykuły HostGrade.pl przygotowuje i aktualizuje redakcja serwisu. Ceny startowe, ceny odnowienia i warunki planów sprawdzamy w cennikach i regulaminach dostawców, a potem liczymy całkowity koszt za 2 lata (cena startowa plus odnowienia). Zasady zbierania danych i liczenia kosztów opisujemy na stronie Metodologia. Linki partnerskie oznaczamy jako #reklama.

[O redakcji i metodologii →](/autorzy/)