 Autor: [Adam Nadolny](/autorzy/adam-nadolny) Ekspert DevOps i infrastruktury · Zweryfikowano Kwiecień 2026

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

# MySQL — optymalizacja i konfiguracja my.cnf

Opublikowano: 9 kwietnia 2026 · Kategoria: Baza danych, VPS

Domyślna konfiguracja MySQL jest bardzo zachowawcza — zaprojektowana żeby działała na słabym sprzęcie, nie żeby była wydajna. Na VPS ze świeżo zainstalowanym MySQL często innodb\_buffer\_pool\_size wynosi zaledwie 128 MB. Przy dobrze dobranej konfiguracji możesz uzyskać 5–10× szybsze zapytania bez zmiany ani linii kodu aplikacji.

## Lokalizacja i struktura my.cnf

\# Typowe lokalizacje my.cnf / mysqld.cnf
# /etc/mysql/my.cnf                   (główny plik)
# /etc/mysql/mysql.conf.d/mysqld.cnf  (Ubuntu/Debian — tu edytuj)
# /etc/my.cnf                          (CentOS/RHEL)

# Sprawdź gdzie MySQL szuka plików konfiguracyjnych
mysqld --help --verbose 2>/dev/null | grep "Default options"

# Sprawdź aktywną konfigurację
mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb\_buffer\_pool\_size';"

## InnoDB Buffer Pool — najważniejszy parametr

InnoDB Buffer Pool to pamięć podręczna danych i indeksów. Jeśli dane mieszczą się w buffer pool, MySQL serwuje je z RAM — bez odczytu dysku. Cel: buffer pool hit ratio **powyżej 99%**.

\# Sprawdź aktualny hit ratio
mysql -u root -p -e "
SELECT
  FORMAT(
    (1 - innodb\_buffer\_pool\_reads / innodb\_buffer\_pool\_read\_requests) \* 100,
    2
  ) AS 'Buffer Pool Hit Ratio %'
FROM information\_schema.INNODB\_METRICS
WHERE name IN ('buffer\_pool\_reads', 'buffer\_pool\_read\_requests')
LIMIT 1;
"

# Lub krócej
mysql -u root -p -e "SHOW STATUS LIKE 'Innodb\_buffer\_pool\_read%';"

## Gotowa konfiguracja — VPS 2 GB RAM

\# /etc/mysql/mysql.conf.d/mysqld.cnf — VPS 2 GB RAM

\[mysqld\]

# === PODSTAWOWE ===
user                    = mysql
bind-address            = 127.0.0.1    # Tylko lokalne połączenia (bezpieczeństwo)
port                    = 3306

# === INNODB BUFFER POOL (kluczowy parametr) ===
# 60% z 2 GB = ~1200 MB
innodb\_buffer\_pool\_size = 1G
innodb\_buffer\_pool\_instances = 1      # 1 na każde GB buffer pool

# === INNODB OGÓLNE ===
innodb\_log\_file\_size    = 256M        # Większy = rzadszy flush = szybszy zapis
innodb\_flush\_log\_at\_trx\_commit = 2   # 1=bezpieczny, 2=szybszy (ryzyko utraty 1s danych)
innodb\_flush\_method     = O\_DIRECT   # Pomija cache OS (lepsze dla dużego buffer pool)

# === POŁĄCZENIA ===
max\_connections         = 100         # PHP-FPM z 20 workerami: max\_connections = workers \* 4
thread\_cache\_size       = 16          # Cache wątków — zmniejsza overhead tworzenia połączeń
wait\_timeout            = 600         # Rozłącz nieaktywne połączenia po 10 min
interactive\_timeout     = 600

# === TABELE TYMCZASOWE ===
# Jeśli tymczasowa tabela przekroczy ten limit, MySQL zapisze ją na dysk
tmp\_table\_size          = 64M
max\_heap\_table\_size     = 64M

# === QUERY CACHE (MYSQL 5.7 TYLKO) ===
# W MySQL 8.0 query\_cache\_type i query\_cache\_size zostały usunięte
# query\_cache\_type      = 0
# query\_cache\_size      = 0

# === SORT I JOIN BUFFERS ===
sort\_buffer\_size        = 2M          # Per połączenie (nie zmniejszaj za bardzo)
join\_buffer\_size        = 2M
read\_rnd\_buffer\_size    = 4M

# === BINLOG (replikacja / point-in-time recovery) ===
# Odkomentuj jeśli używasz replikacji
# log\_bin               = /var/log/mysql/mysql-bin.log
# binlog\_expire\_logs\_seconds = 604800  # 7 dni

# === SLOW QUERY LOG ===
slow\_query\_log          = 1
slow\_query\_log\_file     = /var/log/mysql/slow.log
long\_query\_time         = 1            # Loguj zapytania trwające > 1 sekundy
log\_queries\_not\_using\_indexes = 0      # Ustaw na 1 żeby znaleźć brakujące indeksy

## Gotowa konfiguracja — VPS 4 GB RAM

\# /etc/mysql/mysql.conf.d/mysqld.cnf — VPS 4 GB RAM

\[mysqld\]
bind-address            = 127.0.0.1

# 65% z 4 GB = ~2.6 GB
innodb\_buffer\_pool\_size = 2G
innodb\_buffer\_pool\_instances = 2      # 1 na każde GB buffer pool

innodb\_log\_file\_size    = 512M
innodb\_flush\_log\_at\_trx\_commit = 1    # Pełne bezpieczeństwo (produkcja)
innodb\_flush\_method     = O\_DIRECT
innodb\_io\_capacity      = 400         # IOPS dysku (SSD: 400-2000)
innodb\_io\_capacity\_max  = 2000

max\_connections         = 200
thread\_cache\_size       = 32
wait\_timeout            = 600
interactive\_timeout     = 600

tmp\_table\_size          = 128M
max\_heap\_table\_size     = 128M

sort\_buffer\_size        = 4M
join\_buffer\_size        = 4M
read\_rnd\_buffer\_size    = 8M

slow\_query\_log          = 1
slow\_query\_log\_file     = /var/log/mysql/slow.log
long\_query\_time         = 0.5

## Porównanie parametrów dla różnych rozmiarów RAM

Parametr

VPS 1 GB

VPS 2 GB

VPS 4 GB

VPS 8 GB

`innodb_buffer_pool_size`

512 MB

1 GB

2 GB

5 GB

`innodb_buffer_pool_instances`

1

1

2

4

`max_connections`

50

100

200

400

`tmp_table_size`

32 MB

64 MB

128 MB

256 MB

`innodb_log_file_size`

128 MB

256 MB

512 MB

1 GB

## Analiza slow query log

\# Podsumowanie slow query log (wbudowane narzędzie)
mysqldumpslow -t 10 /var/log/mysql/slow.log
# -t 10 = top 10 najwolniejszych zapytań

# Lepsze narzędzie: pt-query-digest (Percona Toolkit)
sudo apt install percona-toolkit
pt-query-digest /var/log/mysql/slow.log | head -100

# Sprawdź plan wykonania konkretnego zapytania
EXPLAIN SELECT \* FROM wp\_posts WHERE post\_status = 'publish' ORDER BY post\_date DESC LIMIT 10;
# Sprawdź kolumnę "type" — "ALL" = pełny skan tabeli (problem!), "index" lub "ref" = OK

## MySQLTuner — automatyczna analiza

\# Pobierz i uruchom MySQLTuner (po min. 24h działania serwera)
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
perl mysqltuner.pl --user root --pass TwojeHaslo --forcemem 2048

# MySQLTuner wskaże m.in.:
# \[!!\] InnoDB buffer pool / data size: 128.0M / 2.5G  (za mały!)
# \[OK\] Buffer pool hit rate: 99.98%
# \[!!\] Temporary tables created on disk: 35% (za dużo — zwiększ tmp\_table\_size)
# \[!!\] Thread cache hit rate: 85% (zwiększ thread\_cache\_size)

## Najczęstsze pytania

Jaka powinna być wartość innodb\_buffer\_pool\_size? +

InnoDB Buffer Pool to pamięć podręczna danych i indeksów MySQL — im większa, tym więcej danych jest serwowanych z RAM zamiast dysku. Zalecana wartość to 60–70% dostępnej RAM. Na serwerze z 2 GB RAM: 1–1.2 GB (ustaw 1G). Na serwerze z 4 GB RAM: 2.5–2.8 GB (ustaw 2G lub 3G). Na serwerze z 8 GB RAM: 5–6 GB. Upewnij się że po ustawieniu zostaje przynajmniej 512 MB RAM na system operacyjny i PHP-FPM.

Czy query\_cache jest nadal używany w MySQL 8.0? +

Nie. Query Cache (query\_cache\_type, query\_cache\_size) został oznaczony jako deprecated w MySQL 5.7 i całkowicie usunięty w MySQL 8.0. Okazał się anty-wzorcem — przy dużym obciążeniu cache powodował contention (rywalizację o mutex) i spowalniał zapytania zamiast przyspieszać. W MySQL 8.0 zamiast query cache używaj: ProxySQL z cache warstwy proxy, Redis/Memcached do cache aplikacyjnego, lub materialized views dla kosztownych agregatów.

Jak bezpiecznie zrestartować MySQL po zmianach w my.cnf? +

Przed restartem zawsze wykonaj kopię zapasową: mysqldump --all-databases > backup.sql. Następnie sprawdź poprawność konfiguracji: mysqld --validate-config (MySQL 8.0+) lub mysqld --help --verbose > /dev/null. Jeśli nie ma błędów, przeładuj: systemctl restart mysql. Monitoruj logi zaraz po restarcie: journalctl -u mysql -f. Zmiana innodb\_buffer\_pool\_size nie wymaga restartu w MySQL 5.7.5+ — można zmienić dynamicznie przez SET GLOBAL innodb\_buffer\_pool\_size = 1073741824.

Co to jest mysqltuner i jak go uruchomić? +

MySQLTuner to skrypt Perl analizujący statystyki MySQL po minimum 24–48h działania i proponujący zmiany konfiguracji. Uruchom: wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl && perl mysqltuner.pl --user root --pass TwojeHaslo. Skrypt sprawdza m.in.: hit ratio buffer pool (pożądane >99%), użycie thread cache, stosunek tabel tymczasowych na dysku do wszystkich tabel tymczasowych, oraz podaje konkretne sugestie dla my.cnf. Uruchamiaj go ponownie po każdej większej zmianie konfiguracji.

## 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żą pamięcią RAM — idealne dla bazy danych MySQL z dużym buffer pool

Dużo RAM

[Aktywuj rabat →](/out/contabo)

#Reklama · link partnerski

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

LH.pl

Hosting WordPress z MySQL 8.0 i automatyczną optymalizacją bazy danych

MySQL 8.0

[Aktywuj rabat →](/out/lh-pl)

#Reklama · link partnerski

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

Zenbox

Hosting z MariaDB, phpmyadmin i ograniczeniami zasobów per konto

MariaDB

[Aktywuj rabat →](/out/zenbox)

#Reklama · link partnerski

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

## Powiązane strony

-   [MySQL slow query log — analiza i optymalizacja](/baza-wiedzy/mysql-slow-query-log)
-   [MySQL replikacja master-slave](/baza-wiedzy/mysql-replication-master-slave)
-   [MariaDB vs MySQL — porównanie dla hostingu](/baza-wiedzy/mariadb-vs-mysql-hosting)
-   [Wszystkie artykuły](/baza-wiedzy/)