

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)
<a name="wait-event.lwlocksubtransslru"></a>

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 vor Version 13 wird dieses Warteereignis aufgerufen. `SubtransControlLock`
+ `LWLock:SubtransBuffer`: Ein Prozess wartet I/O auf einen einfachen Puffer, der zuletzt zuletzt verwendet wurde (SLRU) für eine Subtransaktion. In RDS für PostgreSQL vor Version 13 wird dieses Warteereignis aufgerufen. `subtrans`

**Topics**
+ [Unterstützte Engine-Versionen](#wait-event.lwlocksubtransslru.supported)
+ [Kontext](#wait-event.lwlocksubtransslru.context)
+ [Wahrscheinliche Ursachen für erhöhte Wartezeiten](#wait-event.lwlocksubtransslru.causes)
+ [Aktionen](#wait-event.lwlocksubtransslru.actions)

## Unterstützte Engine-Versionen
<a name="wait-event.lwlocksubtransslru.supported"></a>

Diese Warteereignisinformationen werden für alle Versionen von RDS für PostgreSQL unterstützt.

## Kontext
<a name="wait-event.lwlocksubtransslru.context"></a>

**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:
+ Transaktions-IDs werden nachverfolgt in `pg_xact`
+ Parent-child Beziehungen werden im `pg_subtrans` Unterverzeichnis unter gespeichert `PGDATA`
+ Jede Datenbanksitzung kann bis zu `64` aktive Untertransaktionen verwalten
+ 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
<a name="wait-event.lwlocksubtransslru.causes"></a>

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 `EXCEPTION` Handlern erstellen automatisch implizite Savepoints, unabhängig davon, ob Ausnahmen** auftreten. Jede initiiert eine neue Subtransaktion. `SAVEPOINT` Wenn eine einzelne Transaktion mehr als 64 Subtransaktionen ansammelt, löst sie einen SLRU-Überlauf für die Subtransaktion aus.
+ **Treiber- und ORM-Konfigurationen** — Die `SAVEPOINT` Verwendung 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 `autosave` auf `always` oder gesetzt ist`conservative`, generiert er vor jeder Abfrage Savepoints.
  + Spring Framework-Transaktionsdefinitionen, wenn auf gesetzt. `propagation_nested`
  + Rails, wenn gesetzt `requires_new: true` ist.
  + SQLAlchemy wann `session.begin_nested` wird verwendet.
  + Django, wenn verschachtelte Blöcke verwendet werden. `atomic()`
  + GORM wann `Savepoint` wird 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:SubtransBuffer` sich `LWLock:SubtransSLRU` in erhöhten Wartezeiten und Sperren.

## Aktionen
<a name="wait-event.lwlocksubtransslru.actions"></a>

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.

**Topics**
+ [Überwachung der Nutzung von Subtransaktionen](#wait-event.lwlocksubtransslru.actions.monitor)
+ [Konfiguration von Speicherparametern](#wait-event.lwlocksubtransslru.actions.memory)
+ [Long-term Aktionen](#wait-event.lwlocksubtransslru.actions.longterm)

### Überwachung der Nutzung von Subtransaktionen
<a name="wait-event.lwlocksubtransslru.actions.monitor"></a>

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
<a name="wait-event.lwlocksubtransslru.actions.memory"></a>

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.

### Long-term Aktionen
<a name="wait-event.lwlocksubtransslru.actions.longterm"></a>
+ **Anwendungscode und Konfigurationen untersuchen** — Überprüfen Sie Ihren Anwendungscode und Ihre Datenbanktreiberkonfigurationen sowohl auf explizite als auch auf implizite Verwendung sowie auf die `SAVEPOINT` Verwendung von Untertransaktionen im Allgemeinen. Identifizieren Sie Transaktionen, die potenziell mehr als 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.  
**Example**  

    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;
    ```  
**Example**  

    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 `autosave` Parameter auf `always` oder gesetzt ist`conservative`, generiert er vor jeder Abfrage Savepoints. Prüfen Sie, ob die `never` Einstellung 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.
+ **Reduzieren Sie lang andauernde Transaktionen — Transaktionen** können Probleme mit Long-running Subtransaktionen verschärfen, indem sie Informationen zu Subtransaktionen länger speichern. Überwachen Sie Performance Insights Insights-Metriken und konfigurieren Sie den `idle_in_transaction_session_timeout` Parameter 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) und `idle_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:SubtransBuffer` und `LWLock:SubtransSLRU` warten Sie, bis Konflikte im Zusammenhang mit Untertransaktionen erkannt werden, bevor sie kritisch werden.