Postmaster używa nadmiernej ilości procesora i zapisu na dysku

9

za pomocą PostgreSQL 9.1.2

Widzę nadmierne zużycie procesora i duże ilości zapisów na dysk z zadań postmastera. Dzieje się tak nawet wtedy, gdy moja aplikacja prawie nic nie robi (10s wkładek na MINUTĘ). Istnieje jednak rozsądna liczba otwartych połączeń.

Próbowałem ustalić, co powoduje to w mojej aplikacji. Jestem całkiem nowy z postgresql i jak dotąd nie dotarłem. Włączyłem niektóre opcje rejestrowania w pliku konfiguracyjnym i sprawdziłem połączenia w tabeli pg_stat_activity, ale wszystkie są bezczynne. Jednak każde połączenie zużywa ~ 50% procesora i zapisuje ~ 15M / s na dysk (nic nie czyta).

Zasadniczo używam giełdowego postgresql.conf z bardzo małymi poprawkami. Byłbym wdzięczny za wszelkie porady i wskazówki, co mogę zrobić, aby to wyśledzić.

Oto próbka tego, co pokazuje mi top / iotop:

Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle

Aktualizacja : Wydaje się, że większość zapisywanych plików dotyczy plików tymczasowych (?) W katalogu $ PG_DATA / base /. Rozumiem tutaj strukturę pliku, że każda tabela jest zasadniczo przechowywana jako plik, którego nazwa to OID tabeli. Istnieje jednak mnóstwo nazwanych plików tnn_nnnnnnni właśnie te pliki wydają się być zapisywane (być może nadpisywane) w sposób ciągły. Do czego służą te pliki? Plików jest ~ 4700, a wszystkie mają rozmiar 8 KB:

-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334

Aktualizacja : Uruchomienie śledzenia procesów postmastera zasadniczo pokazuje wiele rzeczy we / wy pliku:

open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "\0\0\0\0\0\0\0\0\1\0\0\0000\0\360\37\360\37\4 \0\0\0\0b1\5\0\2\0\0\0"..., 8192) = 8192
lseek(18, 0, SEEK_END)                  = 0
close(9)                                = 0
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
close(18)                               = 0
close(9)                                = 0
open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 0
close(9)                                = 0

Aktualizacja : Wydaje się, że ten problem dotyczy wszystkich tabel tymczasowych. Zmieniliśmy naszą konfigurację, aby tabele tymczasowe były tabelami „normalnymi”, a cała aktywność dysku zniknęła, a wydajność powróciła do oczekiwanego poziomu. Ta zmiana była tylko szybkim i nieprzyzwoitym testem: jeśli naprawdę zamierzamy zmienić zwykłe tabele, mamy problemy z współbieżnością i czyszczeniem. Czy tymczasowe stoły naprawdę są złem, czy nadużywamy ich?

Aktualizacja : trochę więcej tła. Korzystam z opracowanego przez siebie oprogramowania pośredniego do replikacji . Jest dość dojrzały i był używany w wielu projektach przez wiele lat, ale używa MySQL. Pracujemy z PostgreSQL dopiero od ostatniego roku lub dwóch. Zasadniczo korzystaliśmy z tabel tymczasowych jako części mechanizmu replikacji. Po każdym ustanowieniu nowego połączenia tworzymy tymczasową tabelę dla każdej tabeli w bazie danych. Przy 10-20 (długotrwałych) połączeniach i ~ 50 tabelach może to stanowić wiele tymczasowych tabel. Wszystkie tabele tymczasowe zostały utworzone za pomocą:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

Semantyka tabel tymczasowych bardzo dobrze wpasowuje się w nasz schemat replikacji i uprościła wiele kodu, którego musieliśmy użyć w MySQL, ale wygląda na to, że implementacja nie była również w porządku. Z części badań, które przeprowadziłem, nie sądzę, aby tabele tymczasowe były naprawdę przeznaczone dla funkcji, w której je wykorzystaliśmy.

Nie jestem wewnętrznym ekspertem (nawet bliskim) na ten temat, tylko jego użytkownikiem, więc moje wyjaśnienie może nie być w 100% dokładne, ale myślę, że jest dość blisko.

Wilk
źródło
3
Twoje zrozumienie jest nieco nieaktualne, jeśli spojrzysz na oficjalną dokumentację , przekonasz się, że „... w przypadku relacji tymczasowych nazwa pliku ma postać tBBB_FFF, gdzie BBB jest identyfikatorem zaplecza, który utworzył plik , a FFF to numer pliku.… ”
Milen A. Radev,
Wow, to dobrze działający podsystem dyskowych operacji we / wy. Co mówi strace o tym, co faktycznie robią pracownicy?
womble
@ MilenA.Radev, więc wygląda na to, że robię coś dziwnego / nadmiernego z tymczasowymi stolikami. To jest interesujące. Mam wiele wyzwalaczy, które korzystają z tabel tymczasowych. Przyjrzę się im bliżej.
wolfcastle
@womble, zaktualizowałem pytanie o dane wyjściowe ze strace.
wolfcastle
Czy rzeczywiście masz problem z wydajnością?
voretaq7

Odpowiedzi:

1

Twoja konfiguracja PostgreSQL jest daleka. To było podejrzane od twojego pierwszego postu,

 Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
 Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
 Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

Z 32 GB na serwerze ~ 25 GB jest darmowe, z wyłączeniem ~ 575 MB bufora.

Z pliku postgresql.conf

 shared_buffers = 32MB                   # min 128kB                               
 #temp_buffers = 8MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 #work_mem = 1MB                         # min 64kB
 #maintenance_work_mem = 16MB            # min 1MB
 #max_stack_depth = 2MB   

Zakładam, że jest to dedykowana baza danych. Jeśli tak, zmień go na następujące parametry i załaduj ponownie / uruchom ponownie,

 shared_buffers = 16GB                   # min 128kB                               
 temp_buffers = 128MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 work_mem = 8MB                         # min 64kB
 maintenance_work_mem = 64MB            # min 1MB
 max_stack_depth = 4MB   

Daj mi znać, jak to zmienia twoje osiągi i mogę je dalej dostosowywać w razie potrzeby.

Jeśli chodzi o niezalogowane tabele, jeśli tabele tymczasowe zawierają dane tymczasowe, które są efemeryczne i, jak wspomniano, są tworzone podczas sesji, lepiej jest używać niezalogowanych tabel.

Możesz skrócić sesję tabelową po sesji, jeśli jest to dopuszczalne.

Więcej informacji tutaj - http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

Nie jestem pewien, dlaczego potrzebujesz tabel tymczasowych do replikacji. Nie możesz używać replikacji strumieniowej PostgreSQL?

Chida
źródło
0

Korzystanie z tabel tymczasowych i utrzymywanie długotrwałych połączeń (prawdopodobnie dotyczy to puli połączeń) może być dużym obciążeniem, jeśli serwer nie jest do tego przygotowany. Jednym z parametrów PostgreSQL, z którym można grać, jest temp_bufferskontrolowanie pamięci RAM przydzielonej do tabel tymczasowych. Te tymczasowe bufory są przydzielane dla każdego połączenia, a wartość domyślna (8 MB) jest prawdopodobnie zbyt niska dla Twojej witryny.

Być może musisz również zmienić nieco zachowanie aplikacji klienckiej, w zależności od sposobu korzystania z tabel tymczasowych. Istnieje podobne pytanie z ładną odpowiedzią na temat przepełnienia stosu .

Tonin
źródło
Będę musiał zapytać mojego wewnętrznego eksperta, czy próbowaliśmy dostosować wartość temp_buffers, czy nie (próbowaliśmy wielu różnych rzeczy). Pytanie, na które wskazujesz, tak naprawdę nie ma zastosowania, ponieważ nie używamy w ten sposób tabel tymczasowych. Zaktualizowałem pytanie o więcej szczegółów.
wolfcastle,
Dziękujemy za aktualizację pytania i plik postgresql.conf. Właśnie dlatego musimy spróbować poprawić tę sytuację. Zgadzam się z odpowiedzią @Chida, która jest zgodna z tym, co sugerowałem wrt temp_buffers. Czy możesz nam również powiedzieć, jaki jest rozmiar bazy danych, którą próbujesz powielić? Ile tabel, średni rozmiar na tabelę i całkowity rozmiar DB?
Tonin,
0

Czy możesz opublikować plik postgresql.conf? Twój postgresql wydaje się znacznie niedostatecznie zoptymalizowany.

Czy możesz także opublikować:

  • Jeśli używasz niezalogowanych tabel do tabel tymczasowych?

  • Ile dysków i w jakiej konfiguracji RAID?

Chida
źródło
Umieściłem tutaj plik postgresql.conf . Uważam, że nie można utworzyć tabeli tymczasowej ORAZ niezalogowanej. W macierzy RAID 1 + 0 znajduje się 6 dysków o pojemności 1 TB (łącznie 3 TB)
Wolfcastle