Postmaster verwendet übermäßige CPU- und Disk Writes

9

mit PostgreSQL 9.1.2

Ich sehe eine übermäßige CPU-Auslastung und große Mengen an Schreibvorgängen von Postmaster-Aufgaben auf die Festplatte. Dies geschieht auch dann, wenn meine Anwendung fast nichts tut (10 Sekunden Einfügungen pro Minute). Es ist jedoch eine angemessene Anzahl von Verbindungen offen.

Ich habe versucht festzustellen, was in meiner Anwendung dies verursacht. Ich bin ziemlich neu in Postgresql und habe bisher noch nichts erreicht. Ich habe einige Protokollierungsoptionen in meiner Konfigurationsdatei aktiviert und die Verbindungen in der Tabelle pg_stat_activity überprüft, aber sie sind alle inaktiv. Jede Verbindung verbraucht jedoch ~ 50% CPU und schreibt ~ 15 M / s auf die Festplatte (liest nichts).

Ich benutze im Grunde die stock postgresql.conf mit sehr kleinen Verbesserungen. Ich würde mich über Ratschläge oder Hinweise freuen, was ich tun kann, um dies aufzuspüren.

Hier ist ein Beispiel dessen, was top / iotop mir zeigt:

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

Update : Ein Großteil des Dateischreibens scheint in temporäre (?) Dateien im Verzeichnis $ PG_DATA / base / zu erfolgen. Mein Verständnis der Dateistruktur hier ist, dass jede Tabelle im Grunde genommen als Datei gespeichert wird, deren Name die OID der Tabelle ist. Es gibt jedoch Unmengen von benannten Dateien tnn_nnnnnnn, und es sind diese Dateien, die scheinbar ständig beschrieben (möglicherweise überschrieben) werden. Wofür sind diese Dateien? Es gibt ~ 4700 Dateien und alle sind 8 KB groß:

-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

Update : Das Ausführen von strace auf den Postmaster-Prozessen zeigt im Grunde eine Menge Datei-E / A-Inhalte:

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

Update : Dieses Problem scheint also alles mit temporären Tabellen zu tun zu haben. Wir haben unser Setup so geändert, dass die temporären Tabellen "normale" Tabellen sind und alle Festplattenaktivitäten weg sind und die Leistung wieder dort ist, wo ich sie erwartet habe. Diese Änderung war nur ein schneller und schmutziger Test: Wenn wir wirklich Änderungen an regulären Tabellen vornehmen wollen, haben wir Probleme mit der Parallelität und der Bereinigung. Sind temporäre Tische wirklich so böse oder missbrauchen wir sie?

Update : Noch etwas Hintergrund. Ich verwende eine eigens entwickelte, auf Anweisungen basierende Replikations-Middleware . Es ist ziemlich ausgereift und wurde über mehrere Jahre in einer Reihe von Projekten verwendet, verwendet jedoch MySQL. Wir haben erst in den letzten ein oder zwei Jahren mit PostgreSQL gearbeitet. Wir haben im Wesentlichen die temporären Tabellen als Teil des Replikationsmechanismus verwendet. Immer wenn eine neue Verbindung hergestellt wird, erstellen wir für jede Tabelle in der Datenbank eine temporäre Tabelle. Bei 10-20 (langlebigen) Verbindungen und ~ 50 Tabellen kann dies viele temporäre Tabellen bedeuten. Alle temporären Tabellen wurden erstellt mit:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

Die Semantik temporärer Tabellen passt sehr gut zu unserem Replikationsschema und vereinfacht einen Großteil des Codes, den wir für MySQL verwenden mussten, aber es sieht so aus, als ob die Implementierung nicht fair war. Nach meiner Recherche glaube ich nicht, dass temporäre Tabellen wirklich für die Funktion gedacht waren, für die wir sie verwendet haben.

Ich bin kein interner Experte (nicht einmal in der Nähe) zu diesem Thema, nur ein Benutzer davon, daher ist meine Erklärung möglicherweise nicht 100% genau, aber ich denke, es ist ziemlich nah.

Wolfsburg
quelle
3
Ihr Verständnis ist etwas veraltet. Wenn Sie sich die offizielle Dokumentation ansehen , werden Sie feststellen, dass "... für temporäre Beziehungen der Dateiname die Form tBBB_FFF hat, wobei BBB die Backend-ID des Backends ist, das die Datei erstellt hat und FFF ist die Filenode-Nummer. ... "
Milen A. Radev
Wow, das ist ein leistungsstarkes Festplatten-E / A-Subsystem. Was sagt Strace über das, was die Arbeiter tatsächlich tun?
womble
@ MilenA.Radev, es sieht also so aus, als würde ich mit temporären Tabellen etwas Seltsames / Übermäßiges machen. Das ist interessant. Ich habe viele Trigger, die temporäre Tabellen verwenden. Ich werde mir diese genauer ansehen.
Wolfcastle
@womble, ich habe die Frage mit Ausgabe von strace aktualisiert.
Wolfcastle
Tritt tatsächlich ein Leistungsproblem auf?
voretaq7

Antworten:

1

Ihre PostgreSQL-Konfiguration ist weit entfernt. Dies war verdächtig von Ihrem ersten Beitrag,

 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

Von 32 GB auf Ihrem Server sind ~ 25 GB kostenlos, ausgenommen ~ 575 MB Puffer.

Aus Ihrer postgresql.conf-Datei,

 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   

Ich gehe davon aus, dass dies eine dedizierte Datenbank ist. Wenn ja, ändern Sie es in die folgenden Parameter und laden Sie es neu / starten Sie es neu.

 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   

Lassen Sie mich wissen, wie sich dadurch Ihre Leistung ändert, und können Sie sie bei Bedarf weiter optimieren.

In Bezug auf nicht protokollierte Tabellen: Wenn Ihre temporären Tabellen kurzlebige temporäre Daten enthalten und, wie Sie erwähnt haben, in einer Sitzung erstellt werden, ist es besser, nicht protokollierte Tabellen zu verwenden.

Sie können Ihre Tabellen nach der Sitzung abschneiden, wenn dies akzeptabel ist.

Weitere Informationen hier - http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

Ich bin mir nicht sicher, warum Sie temporäre Tabellen für die Replikation benötigen. Können Sie die PostgreSQL-Streaming-Replikation nicht verwenden?

Chida
quelle
0

Die Verwendung temporärer Tabellen und langjährige Verbindungen (wahrscheinlich handelt es sich um Verbindungspooling) kann eine Belastung sein, wenn Ihr Server nicht darauf vorbereitet ist. Ein PostgreSQL-Parameter, mit dem Sie spielen können, temp_bufferssteuert den RAM, der temporären Tabellen zugewiesen ist. Diese temporären Puffer werden pro Verbindung zugewiesen und der Standardwert (8 MB) ist wahrscheinlich zu niedrig für Ihre Site.

Möglicherweise müssen Sie auch das Verhalten Ihrer Clientanwendung etwas ändern, je nachdem, wie Sie Ihre temporären Tabellen verwenden. Es gibt eine ähnliche Frage mit einer schönen Antwort auf Stack Overflow .

Tonin
quelle
Ich muss meinen internen Experten fragen, ob wir versucht haben, den Wert für temp_buffers anzupassen oder nicht (wir haben viele verschiedene Dinge ausprobiert). Die Frage, auf die Sie hinweisen, trifft nicht wirklich zu, da wir auf diese Weise keine temporären Tabellen verwenden. Ich habe die Frage mit einigen weiteren Details aktualisiert.
Wolfcastle
Vielen Dank für das Update der Frage und für die Datei postgresql.conf. Wir müssen versuchen, diese Situation zu verbessern. Ich stimme der Antwort von @Chida zu, die mit dem übereinstimmt, was ich vorgeschlagen habe temp_buffers. Können Sie uns auch mitteilen, wie groß die Datenbank ist, die Sie replizieren möchten? Wie viele Tabellen, mittlere Größe pro Tabelle und Gesamtgröße der Datenbank?
Tonin
0

Könnten Sie Ihre postgresql.conf-Datei veröffentlichen? Ihr Postgresql scheint deutlich unteroptimiert zu sein.

Könntest du auch posten:

  • Wenn Sie nicht protokollierte Tabellen für Ihre temporären Tabellen verwenden?

  • Wie viele Festplatten und in welcher RAID-Konfiguration?

Chida
quelle
Ich habe die Datei postgresql.conf hier abgelegt . Ich glaube, Sie können keine Tabelle erstellen, die sowohl temporär als auch nicht protokolliert ist. Es gibt 6 1 TB Festplatten in einem RAID 1 + 0 (3 TB Gesamtspeicher)
Wolfcastle