Warum die Django-Sitzungstabelle unter PostgreSQL wächst

7

Ich verwende PostgreSQL 9.1.6 über PgBouncer 1.4.2 in meinem Django 1.4.8-Projekt. django_sessionTisch wächst die ganze Zeit. VAKUUM hilft nicht. VACUUM FULL läuft stundenlang. Nur TRUNCATEhilft in der Regel.

Die Tabelle enthält Zeilen von ca. 10 KB. Es wird 40 Mal pro Sekunde aktualisiert.

# SELECT table_name, pg_size_pretty(table_size) AS table_size, pg_size_pretty(indexes_size) AS indexes_size, pg_size_pretty(total_size) AS total_size
FROM (
    SELECT table_name, pg_table_size(table_name) AS table_size, pg_indexes_size(table_name) AS indexes_size, pg_total_relation_size(table_name) AS total_size
    FROM (
        SELECT ('"' || table_schema || '"."' || table_name || '"') AS table_name
        FROM information_schema.tables
    ) AS all_tables ORDER BY total_size DESC LIMIT 1
) AS pretty_sizes;
        table_name         | table_size | indexes_size | total_size 
---------------------------+------------+--------------+------------
 "public"."django_session" | 35 GB      | 209 MB       | 35 GB
(1 row)

# SELECT COUNT(*) FROM django_session;
 count 
-------
 40196

Ein Bereinigungsbefehl wird jede Nacht von cron ausgeführt.

./manage.py cleanup && echo "vacuum (analyze, verbose);" | ./manage.py dbshell

Django_session hat etwas Interessantes in der Ausgabe.

INFO:  vacuuming "public.django_session"
INFO:  scanned index "django_session_pkey" to remove 5338 row versions
DETAIL:  CPU 0.00s/0.00u sec elapsed 0.01 sec.
INFO:  scanned index "django_session_expire_date" to remove 5338 row versions
DETAIL:  CPU 0.10s/0.06u sec elapsed 3.47 sec.
INFO:  "django_session": removed 5338 row versions in 187 pages
DETAIL:  CPU 0.00s/0.00u sec elapsed 0.01 sec.
INFO:  index "django_session_pkey" now contains 71568 row versions in 1647 pages
DETAIL:  0 index row versions were removed.
4 index pages have been deleted, 4 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  index "django_session_expire_date" now contains 71568 row versions in 25049 pages
DETAIL:  2785 index row versions were removed.
1804 index pages have been deleted, 1798 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "django_session": found 0 removable, 71568 nonremovable row versions in 3386 out of 3386 pages
DETAIL:  46699 dead row versions cannot be removed yet.
There were 811150 unused item pointers.
0 pages are entirely empty.
CPU 0.11s/0.10u sec elapsed 16.00 sec.
...
INFO:  analyzing "public.django_session"
INFO:  "django_session": scanned 3460 of 3460 pages, containing 25514 live rows and 288939 dead rows; 25514 rows in sample, 25514 estimated total rows

Ich wundere mich über 46699 Dead Row-Versionen , 811150 nicht verwendete Item-Zeiger und 288939 Dead Row . Viele Quellen sagen, das Problem liege in "Leerlauf in Transaktions" -Prozessen. Ich dachte, das ist mein Fall, weil es viele solcher Prozesse gibt:

# SELECT COUNT(*) FROM pg_stat_activity WHERE current_query = '<IDLE> in transaction';
 count 
-------
    30

Aber es gibt keine wirklich alte Abfrage.

# SELECT age(now(), query_start) AS "age" FROM pg_stat_activity ORDER BY query_start LIMIT 1;
       age       
-----------------
 00:00:00.241521

Eine große Anzahl von Leerlaufprozessen wird wahrscheinlich durch TransactionMiddleware verursacht.

Jetzt habe ich keine Ahnung. Ich habe den Bereinigungsbefehl manuell ausgeführt und er hat gut funktioniert, also habe ich festgestellt, dass das Problem irgendwie behoben ist, und die Tabelle abgeschnitten. Aber es wächst wieder.

Tabellenwachstumsdiagramm

# select * from pgstattuple('django_session');
-[ RECORD 1 ]------+---------
table_len          | 23003136
tuple_count        | 32139
tuple_len          | 11201544
tuple_percent      | 48.7
dead_tuple_count   | 1729
dead_tuple_len     | 171632
dead_tuple_percent | 0.75
free_space         | 8930044
free_percent       | 38.82

Was kann solch ein seltsames Problem verursachen?

AKTUALISIEREN:

Ich habe TransactionMiddleware entfernt und in PgBouncer in den Transaktionsmodus gewechselt. Derzeit gibt es fast keine Transaktionsprozesse im Leerlauf. Das hilft aber nicht.

$ echo $(for i in `seq 100`; do echo "SELECT COUNT(*) FROM pg_stat_activity WHERE current_query = '<IDLE> in transaction';" | sudo -u postgres psql mydb | grep  ' 0'; sleep 0.1; done | wc -l)"% of time there is NO idle in transaction processes"

75% of time there is NO idle in transaction processes
Raacer
quelle
1
"Leerlauf in Transaktion" führt zu einem VAKUUM, der keine Datensätze bereinigen kann, die ich möglicherweise in diesen Transaktionen verwendet habe. Was verursacht diese Leerlauftransaktionen?
Frank Heikens
Danke für deinen Kommentar! Ich denke, sie werden durch den PgBouncer-Sitzungsmodus und TransactionMiddleware verursacht. Alle http-Anforderungsprozessoren wurden in eine einzelne Datenbanktransaktion eingebunden und verwendeten eine dauerhafte Datenbankverbindung. Aber jetzt habe ich TransactionMiddleware deaktiviert und pgbouncer in den Transaktionsmodus geschaltet, sodass keine Transaktionen mehr ausgeführt werden und keine dauerhafte Verbindung mehr besteht. Die Anzahl der '<IDLE> in Transaktions'-Prozessen ist jetzt 0 (und manchmal 1). Es scheint also, dass "Leerlauf in der Transaktion" für mich kein Problem ist, oder?
Raacer

Antworten:

0

Zuerst! Aktualisieren Sie auf 9.1.10 (installieren Sie einfach neue Binärdateien und starten Sie die Datenbank neu).

Ich würde folgendes tun:

  1. Stellen Sie sicher, dass keine Sitzungen mit langer Laufzeit ausgeführt werden. Dies bedeutet, dass keine langen Transaktionen durchgeführt werden.
  2. Sie haben Ihre autovacuumEinstellungen nicht erwähnt , daher würde ich sicherstellen, dass sie autovacuumausgeführt werden.
  3. Ich hätte die Autovakuumschwellen für die betreffende Tabelle angepasst django_session.
  4. CLUSTER die Tabelle unter Verwendung des Primärschlüsselindex.

Es ist auch sehr interessant, den Inhalt der pg_stat_%Ansichten für diese bestimmte Tabelle zu überprüfen . Ich habe das Gefühl, gemessen an der großen Anzahl toter Einträge im PK-Index, dass Django dynamische UPDATEAbfragen erstellt, die alle Spalten des Tupels aktualisieren . Wenn dies zutrifft, erklärt dies die Situation, die Sie sehen.

vyegorov
quelle
0

OK, das ist meine Antwort nach vielen Recherchen.

Führen Sie keinen hochgeladenen PostgreSQL-Server auf einer virtuellen Maschine wie KVM aus. Selbst mit einem geeigneten Treiber für den direkten Zugriff auf die Festplatte fehlt die E / A-Geschwindigkeit.

Raacer
quelle