Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
LWLock:SubtransSLRU (LWLock:SubtransControlLock)
Die Ereignisse LWLock:SubtransSLRU und LWLock:SubtransBuffer wait weisen darauf hin, dass eine Sitzung darauf wartet, auf den SLRU-Cache (Simple Least-Recently Used) für Subtransaktionsinformationen zuzugreifen. Dies tritt auf, wenn die Sichtbarkeit von Transaktionen und die Beziehungen zwischen Eltern und Kindern bestimmt werden.
-
LWLock:SubtransSLRU: Ein Prozess wartet darauf, für eine Subtransaktion auf den Simple Least-Recently Used (SLRU) -Cache zuzugreifen. In RDS für PostgreSQL vor Version 13 wird dieses Wait-Ereignis aufgerufen.SubtransControlLock -
LWLock:SubtransBuffer: Ein Prozess wartet I/O auf einen einfachen, am wenigsten zuletzt verwendeten (SLRU) -Puffer für eine Subtransaktion. In RDS für PostgreSQL vor Version 13 wird dieses Wait-Ereignis aufgerufen.subtrans
Unterstützte Engine-Versionen
Diese Warteereignisinformationen werden für alle Versionen von RDS für PostgreSQL unterstützt.
Kontext
Grundlegendes zu Subtransaktionen — Eine Subtransaktion ist eine Transaktion innerhalb einer Transaktion in PostgreSQL. Sie wird auch als verschachtelte Transaktion bezeichnet.
Subtransaktionen werden normalerweise erstellt, wenn Sie Folgendes verwenden:
-
SAVEPOINT-Befehle -
Ausnahme-Blöcke ()
BEGIN/EXCEPTION/END
Mit Subtransaktionen können Sie Teile einer Transaktion rückgängig machen, ohne dass sich dies auf die gesamte Transaktion auswirkt. Dies gibt Ihnen eine genaue Kontrolle über das Transaktionsmanagement.
Implementierungsdetails — PostgreSQL implementiert Subtransaktionen als verschachtelte Strukturen innerhalb der Haupttransaktionen. Jede Subtransaktion erhält ihre eigene Transaktions-ID.
Wichtige Aspekte der Implementierung:
-
Transaktions-IDs werden nachverfolgt
pg_xact -
Parent-child Beziehungen werden im
pg_subtransUnterverzeichnis unter gespeichertPGDATA -
Jede Datenbanksitzung kann bis zu
64aktive Subtransaktionen verwalten -
Das Überschreiten dieses Limits führt zu einem Subtransaktionsüberlauf, der den Zugriff auf den Simple Least-Recently Used (SLRU) -Cache für Subtransaktionsinformationen erfordert
Wahrscheinliche Ursachen für erhöhte Wartezeiten
Zu den häufigsten Ursachen für SLRU-Konflikte bei Subtransaktionen gehören:
-
Übermäßiger Gebrauch der SAVEPOINT- und EXCEPTION-Behandlung — PL/pgSQL Prozeduren mit
EXCEPTIONHandlern erstellen automatisch implizite Savepoints, unabhängig davon, ob Ausnahmen auftreten. Jede initiiert eine neue Subtransaktion.SAVEPOINTWenn eine einzelne Transaktion mehr als 64 Subtransaktionen ansammelt, löst sie einen SLRU-Überlauf für die Subtransaktion aus. -
Treiber- und ORM-Konfigurationen — Die
SAVEPOINTVerwendung kann explizit im Anwendungscode oder implizit durch Treiberkonfigurationen erfolgen. Viele häufig verwendete ORM-Tools und Anwendungsframeworks unterstützen verschachtelte Transaktionen nativ. Hier sind einige gängige Beispiele:-
Wenn der JDBC-Treiberparameter
autosaveaufalwaysoder gesetzt istconservative, generiert er Savepoints vor jeder Abfrage. -
Spring Framework-Transaktionsdefinitionen, wenn sie auf gesetzt sind.
propagation_nested -
Rails, wenn gesetzt
requires_new: trueist. -
SQLAlchemy, wenn verwendet wird
session.begin_nested. -
Django, wenn verschachtelte Blöcke verwendet werden.
atomic() -
GORM, wenn verwendet wird
Savepoint. -
psqlODBC, wenn die Einstellung der Rollback-Ebene auf Rollback auf Anweisungsebene gesetzt ist (z. B.).
PROTOCOL=7.4-2
-
-
Hohe gleichzeitige Workloads mit lang andauernden Transaktionen und Subtransaktionen — Wenn bei hohen gleichzeitigen Workloads und lang andauernden Transaktionen und Subtransaktionen ein SLRU-Überlauf für Subtransaktionen auftritt, kommt es bei PostgreSQL zu vermehrten Konflikten. Dies äußert
LWLock:SubtransBuffersichLWLock:SubtransSLRUin erhöhten Wartezeiten und Sperren.
Aktionen
Abhängig von den Ursachen Ihres Warteereignisses empfehlen wir verschiedene Aktionen. Einige Maßnahmen bieten sofortige Abhilfe, während bei anderen eine Untersuchung und eine langfristige Korrektur erforderlich sind.
Themen
Überwachung der Nutzung von Subtransaktionen
Verwenden Sie für PostgreSQL-Versionen 16.1 und höher die folgende Abfrage, um die Anzahl der Subtransaktionen und den Überlaufstatus pro Backend zu überwachen. Diese Abfrage verknüpft Backend-Statistiken mit Aktivitätsinformationen, um zu zeigen, welche Prozesse Subtransaktionen verwenden:
SELECT a.pid, usename, query, state, wait_event_type, wait_event, subxact_count, subxact_overflowed FROM (SELECT id, pg_stat_get_backend_pid(id) pid, subxact_count, subxact_overflowed FROM pg_stat_get_backend_idset() id JOIN LATERAL pg_stat_get_backend_subxact(id) AS s ON true ) a JOIN pg_stat_activity b ON a.pid = b.pid;
Überwachen Sie bei PostgreSQL-Versionen 13.3 und höher die pg_stat_slru Ansicht auf den Druck des Subtransaktions-Caches. Die folgende SQL-Abfrage ruft SLRU-Cache-Statistiken für die Subtrans-Komponente ab:
SELECT * FROM pg_stat_slru WHERE name = 'Subtrans';
Ein konstant steigender blks_read Wert weist auf häufigen Festplattenzugriff für nicht zwischengespeicherte Subtransaktionen hin, was auf eine potenzielle Belastung des SLRU-Cache hinweist.
Konfiguration von Speicherparametern
Für PostgreSQL 17.1 und höher können Sie die SLRU-Cachegröße der Subtransaktion mithilfe des Parameters konfigurieren. subtransaction_buffers Das folgende Konfigurationsbeispiel zeigt, wie der Subtransaktionspufferparameter festgelegt wird:
subtransaction_buffers = 128
Dieser Parameter gibt die Menge an gemeinsam genutztem Speicher an, der zum Zwischenspeichern von Subtransaktionsinhalten () pg_subtrans verwendet wird. Wenn der Wert ohne Einheiten angegeben wird, steht er für BLCKSZ Byteblöcke, in der Regel jeweils 8 KB. Wenn Sie den Wert beispielsweise auf 128 setzen, wird dem Subtransaktions-Cache 1 MB (128 * 8 kB) Speicher zugewiesen.
Anmerkung
Sie können diesen Parameter auf Clusterebene festlegen, sodass alle Instanzen konsistent bleiben. Testen Sie den Wert und passen Sie ihn an Ihre spezifischen Workload-Anforderungen und Instance-Klasse an. Sie müssen die Writer-Instanz neu starten, damit die Parameteränderungen wirksam werden.
Long-term Aktionen
-
Anwendungscode und Konfigurationen untersuchen — Prüfen Sie den Anwendungscode und die Datenbanktreiberkonfigurationen auf explizite und implizite Nutzung sowie auf die
SAVEPOINTVerwendung von Subtransaktionen im Allgemeinen. Identifizieren Sie Transaktionen, die potenziell über 64 Subtransaktionen generieren. -
Reduzieren Sie die Nutzung von Savepoints — Minimieren Sie die Verwendung von Savepoints in Ihren Transaktionen:
-
Überprüfen Sie PL/pgSQL Verfahren und Funktionen mit EXCEPTION-Blöcken. EXCEPTION-Blöcke erzeugen automatisch implizite Savepoints, die zum Überlauf von Subtransaktionen beitragen können. Jede EXCEPTION-Klausel erstellt eine Subtransaktion, unabhängig davon, ob während der Ausführung tatsächlich eine Ausnahme auftritt.
Beispiel
Beispiel 1: Problematische Verwendung des EXCEPTION-Blocks
Das folgende Codebeispiel zeigt die problematische Verwendung von EXCEPTION-Blocks, die mehrere Subtransaktionen erzeugt:
CREATE OR REPLACE FUNCTION process_user_data() RETURNS void AS $$ DECLARE user_record RECORD; BEGIN FOR user_record IN SELECT * FROM users LOOP BEGIN -- This creates a subtransaction for each iteration INSERT INTO user_audit (user_id, action, timestamp) VALUES (user_record.id, 'processed', NOW()); UPDATE users SET last_processed = NOW() WHERE id = user_record.id; EXCEPTION WHEN unique_violation THEN -- Handle duplicate audit entries UPDATE user_audit SET timestamp = NOW() WHERE user_id = user_record.id AND action = 'processed'; END; END LOOP; END; $$ LANGUAGE plpgsql;Das folgende verbesserte Codebeispiel reduziert die Verwendung von Subtransaktionen, indem UPSERT anstelle der Ausnahmebehandlung verwendet wird:
CREATE OR REPLACE FUNCTION process_user_data() RETURNS void AS $$ DECLARE user_record RECORD; BEGIN FOR user_record IN SELECT * FROM users LOOP -- Use UPSERT to avoid exception handling INSERT INTO user_audit (user_id, action, timestamp) VALUES (user_record.id, 'processed', NOW()) ON CONFLICT (user_id, action) DO UPDATE SET timestamp = NOW(); UPDATE users SET last_processed = NOW() WHERE id = user_record.id; END LOOP; END; $$ LANGUAGE plpgsql;Beispiel
Beispiel 2: STRICT-Ausnahmebehandler
Das folgende Codebeispiel zeigt die problematische EXCEPTION-Behandlung mit NO_DATA_FOUND:
CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER) RETURNS TEXT AS $$ DECLARE user_email TEXT; BEGIN BEGIN -- STRICT causes an exception if no rows or multiple rows found SELECT email INTO STRICT user_email FROM users WHERE id = p_user_id; RETURN user_email; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 'Email not found'; END; END; $$ LANGUAGE plpgsql;Das folgende verbesserte Codebeispiel vermeidet Subtransaktionen, indem IF NOT FOUND anstelle der Ausnahmebehandlung verwendet wird:
CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER) RETURNS TEXT AS $$ DECLARE user_email TEXT; BEGIN SELECT email INTO user_email FROM users WHERE id = p_user_id; IF NOT FOUND THEN RETURN 'Email not found'; ELSE RETURN user_email; END IF; END; $$ LANGUAGE plpgsql; -
JDBC-Treiber — Wenn der
autosaveParameter aufalwaysoder gesetzt istconservative, generiert er Savepoints vor jeder Abfrage. Prüfen Sie, ob dieneverEinstellung für Ihre Anwendung akzeptabel wäre. -
PostgreSQL ODBC-Treiber (psqlODBC) — Die Rollback-Level-Einstellung (für Rollback auf Anweisungsebene) erstellt implizite Savepoints, um die Rollback-Funktionalität von Anweisungen zu aktivieren. Prüfen Sie, ob ein Rollback auf Transaktionsebene oder kein Rollback für Ihre Anwendung akzeptabel wäre.
-
Untersuchen Sie die ORM-Transaktion
-
Erwägen Sie alternative Strategien zur Fehlerbehandlung, für die keine Savepoints erforderlich sind
-
-
Optimieren Sie das Transaktionsdesign — Strukturieren Sie Transaktionen um, um übermäßige Verschachtelungen zu vermeiden und die Wahrscheinlichkeit eines Überlaufs von Subtransaktionen zu verringern.
-
Reduzieren Sie lang andauernde Transaktionen — Transaktionen können die Probleme mit Long-running Subtransaktionen verschärfen, da sie die Subtransaktionsinformationen länger speichern. Überwachen Sie detaillierte Zählermesswerte pro Abfrage und Datenbank und konfigurieren Sie den
idle_in_transaction_session_timeoutParameter so, dass inaktive Transaktionen automatisch beendet werden. -
Überwachen Sie detaillierte Zählermetriken pro Abfrage und Datenbank — Verfolgen Sie Kennzahlen wie
idle_in_transaction_count(Anzahl der inaktiven Sitzungen im Transaktionsstatus) undidle_in_transaction_max_time(Dauer der am längsten laufenden Transaktion im Leerlauf), um Transaktionen mit langer Laufzeit zu erkennen. -
Konfigurieren
idle_in_transaction_session_timeout— Stellen Sie diesen Parameter in Ihrer Parametergruppe ein, um Transaktionen im Leerlauf nach einer bestimmten Dauer automatisch zu beenden. -
Proaktive Überwachung — Achten Sie auf häufiges Auftreten von Ereignissen
LWLock:SubtransBufferundLWLock:SubtransSLRUwarten Sie ab, um Konflikte im Zusammenhang mit Untertransaktionen zu erkennen, bevor sie kritisch werden.