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
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 übergeordneten und untergeordneten Objekten bestimmt werden.
-
LWLock:SubtransSLRU: Ein Prozess wartet darauf, auf den einfachen SLRU-Cache (Least-Recently Used) für eine Subtransaktion zuzugreifen. In RDS für PostgreSQL 12.22 und früher wird dieses Warteereignis aufgerufen.SubtransControlLock -
LWLock:SubtransBuffer: Ein Prozess wartet auf einen einfachen Puffer ( I/O Least-Recently Used, SLRU) für eine Subtransaktion. In RDS für PostgreSQL 12.22 und früher wird dieses Warteereignis aufgerufen.subtrans
Unterstützte Engine-Versionen
Diese Informationen zum Warteereignis werden für alle Versionen von unterstützt.
Kontext
Subtransaktionen verstehen — Eine Subtransaktion ist eine Transaktion innerhalb einer Transaktion in PostgreSQL. Sie wird auch als verschachtelte Transaktion bezeichnet.
Untertransaktionen werden normalerweise erstellt, wenn Sie Folgendes verwenden:
-
SAVEPOINT-Befehle -
Ausnahmeblöcke ()
BEGIN/EXCEPTION/END
Mit Untertransaktionen können Sie Teile einer Transaktion rückgängig machen, ohne dass sich dies auf die gesamte Transaktion auswirkt. Auf diese Weise haben Sie eine detaillierte Kontrolle über das Transaktionsmanagement.
Implementierungsdetails — PostgreSQL implementiert Subtransaktionen als verschachtelte Strukturen innerhalb von Haupttransaktionen. Jede Subtransaktion erhält ihre eigene Transaktions-ID.
Die wichtigsten Aspekte der Implementierung:
-
Transaktionen IDs werden nachverfolgt
pg_xact -
Beziehungen zwischen Eltern und Kindern werden im
pg_subtransUnterverzeichnis unter gespeichertPGDATA -
In jeder Datenbanksitzung können bis zu aktive Untertransaktionen verwaltet werden
64 -
Eine Überschreitung dieses Limits führt zu einem Überlauf der Subtransaktionen, was den Zugriff auf den SLRU-Cache (Simple Least-Recently Used) für Subtransaktionsinformationen erfordert
Wahrscheinliche Ursachen für erhöhte Wartezeiten
Zu den häufigsten Ursachen für Konflikte mit der Subtransaktion SLRU gehören:
-
Übermäßiger Einsatz von 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 vor jeder Abfrage Savepoints. -
Spring Framework-Transaktionsdefinitionen, wenn auf gesetzt.
propagation_nested -
Rails, wenn gesetzt
requires_new: trueist. -
SQLAlchemy wann
session.begin_nestedwird verwendet. -
Django, wenn verschachtelte
atomic()Blöcke verwendet werden. -
GORM wann
Savepointwird verwendet. -
psqlODBC, wenn die Einstellung der Rollback-Stufe 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 der Subtransaktion auftritt, kommt es bei PostgreSQL zu erhöhten 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 andere Untersuchungen und langfristige Korrekturen erfordern.
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-Cachestatistiken 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 Untertransaktionen hin, was auf eine potenzielle Belastung des SLRU-Caches hindeutet.
Konfiguration von Speicherparametern
Für PostgreSQL 17.1 und höher können Sie die Größe des SLRU-Caches der Subtransaktion mithilfe des Parameters konfigurieren. subtransaction_buffers Das folgende Konfigurationsbeispiel zeigt, wie der Parameter für den Subtransaktionspuffer festgelegt wird:
subtransaction_buffers = 128
Dieser Parameter gibt die Menge an gemeinsam genutztem Speicher an, die 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 1 MB (128 * 8 KB) Speicher für den Subtransaktions-Cache 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 Ihre Instance-Klasse an. Sie müssen die Writer-Instanz neu starten, damit die Parameteränderungen wirksam werden.
Langfristige Maßnahmen
-
Überprüfen Sie den Anwendungscode und die Konfigurationen — Überprüfen Sie Ihren Anwendungscode und Ihre Datenbanktreiberkonfigurationen auf explizite und implizite Verwendung sowie auf die
SAVEPOINTVerwendung von Untertransaktionen im Allgemeinen. Identifizieren Sie Transaktionen, die potenziell über 64 Untertransaktionen 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 erstellen automatisch implizite Savepoints, die zu einem Überlauf von Subtransaktionen beitragen können. Jede EXCEPTION-Klausel erstellt eine Untertransaktion, unabhängig davon, ob während der Ausführung tatsächlich eine Ausnahme auftritt.
Beispiel 1: Problematische Verwendung von EXCEPTION-Blocks
Das folgende Codebeispiel zeigt die problematische Verwendung von EXCEPTION-Blocks, die mehrere Untertransaktionen 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 Nutzung 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 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 Untertransaktionen, 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 vor jeder Abfrage Savepoints. 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 für Anweisungen zu aktivieren. Prüfen Sie, ob ein Rollback auf Transaktionsebene oder kein Rollback für Ihre Anwendung akzeptabel wäre.
-
Untersuchen Sie ORM-Transaktionskonfigur
-
Erwägen Sie alternative Strategien zur Fehlerbehandlung, für die keine Savepoints erforderlich sind
-
-
Optimieren Sie das Transaktionsdesign — Strukturieren Sie Transaktionen neu, um übermäßige Verschachtelungen zu vermeiden und die Wahrscheinlichkeit eines Überlaufs von Subtransaktionen zu verringern.
-
Reduzierung lang andauernder Transaktionen — Langfristige Transaktionen können Probleme mit Subtransaktionen verschärfen, da sie die Informationen zu Subtransaktionen länger speichern. Überwachen Sie Performance Insights Insights-Metriken und konfigurieren Sie den
idle_in_transaction_session_timeoutParameter so, dass inaktive Transaktionen automatisch beendet werden. -
Performance Insights Insights-Metriken überwachen — Verfolgen Sie Metriken wie
idle_in_transaction_count(Anzahl der inaktiven Sitzungen im Transaktionsstatus) undidle_in_transaction_max_time(Dauer der am längsten laufenden inaktiven Transaktion), um Transaktionen mit langer Laufzeit zu erkennen. -
Konfigurieren
idle_in_transaction_session_timeout— Stellen Sie diesen Parameter in Ihrer Parametergruppe so ein, dass inaktive Transaktionen nach einer bestimmten Dauer automatisch beendet werden. -
Proaktive Überwachung — Überwachen Sie häufig auftretende Ereignisse
LWLock:SubtransBufferundLWLock:SubtransSLRUwarten Sie, bis Konflikte im Zusammenhang mit Untertransaktionen erkannt werden, bevor sie kritisch werden.