

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
<a name="wait-event.lwlocksubtransslru"></a>

Gli eventi `LWLock:SubtransSLRU` and `LWLock:SubtransBuffer` wait indicano che una sessione è in attesa di accedere alla cache SLRU (Simple Least-Recently Used) per le informazioni sulle sottotransazioni. Ciò si verifica quando si determina la visibilità delle transazioni e le relazioni padre-figlio.
+ `LWLock:SubtransSLRU`: Un processo è in attesa di accedere alla cache SLRU (Simple Least-Recently Used) per una sottotransazione. In RDS per PostgreSQL precedente alla versione 13, viene chiamato questo evento di attesa. `SubtransControlLock`
+ `LWLock:SubtransBuffer`: Un processo è in attesa I/O su un semplice buffer SLRU (Least-Recently Used) per una sottotransazione. In RDS per PostgreSQL precedente alla versione 13, viene chiamato questo evento di attesa. `subtrans`

**Topics**
+ [Versioni del motore supportate](#wait-event.lwlocksubtransslru.supported)
+ [Contesto](#wait-event.lwlocksubtransslru.context)
+ [Probabili cause di aumento delle attese](#wait-event.lwlocksubtransslru.causes)
+ [Azioni](#wait-event.lwlocksubtransslru.actions)

## Versioni del motore supportate
<a name="wait-event.lwlocksubtransslru.supported"></a>

Queste informazioni relative all'evento di attesa sono supportate per tutte le versioni di RDS per PostgreSQL.

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

**Comprendere le sottotransazioni**: una sottotransazione è una transazione all'interno di una transazione in PostgreSQL. È anche nota come transazione annidata.

Le sottotransazioni vengono in genere create quando si utilizza:
+ Comandi `SAVEPOINT`
+ Blocchi di eccezioni () `BEGIN/EXCEPTION/END`

Le sottotransazioni consentono di ripristinare parti di una transazione senza influire sull'intera transazione. Questo ti offre un controllo granulare sulla gestione delle transazioni.

**Dettagli di implementazione**: PostgreSQL implementa le sottotransazioni come strutture annidate all'interno delle transazioni principali. Ogni sottotransazione ottiene il proprio ID di transazione.

Aspetti chiave dell'implementazione:
+ Gli ID delle transazioni vengono tracciati `pg_xact`
+ Parent-child le relazioni sono archiviate nella `pg_subtrans` sottodirectory in `PGDATA`
+ Ogni sessione del database può mantenere fino a sottotransazioni `64` attive
+ Il superamento di questo limite causa un overflow delle sottotransazioni, che richiede l'accesso alla cache SLRU (Simple Least-Recently Used) per le informazioni sulle sottotransazioni

## Probabili cause di aumento delle attese
<a name="wait-event.lwlocksubtransslru.causes"></a>

Le cause più comuni di contesa SLRU per le sottotransazioni includono:
+ **Uso eccessivo della gestione di SAVEPOINT e EXCEPTION: PL/pgSQL le procedure con `EXCEPTION` gestori** creano automaticamente punti di salvataggio impliciti, indipendentemente dal fatto che si verifichino eccezioni. Ciascuno avvia una nuova sottotransazione. `SAVEPOINT` Quando una singola transazione accumula più di 64 sottotransazioni, attiva un overflow SLRU di sottotransazione.
+ Configurazioni di **driver e ORM: l'`SAVEPOINT`utilizzo può essere esplicito nel codice dell'applicazione o implicito nelle configurazioni** dei driver. Molti strumenti ORM e framework applicativi di uso comune supportano le transazioni annidate in modo nativo. Ecco alcuni esempi comuni:
  + Il parametro del driver JDBC`autosave`, se impostato su `always` o`conservative`, genera punti di salvataggio prima di ogni query.
  + Definizioni delle transazioni Spring Framework quando impostato su. `propagation_nested`
  + Rails quando `requires_new: true` è impostato.
  + SQLAlchemy quando viene usato. `session.begin_nested`
  + Django quando vengono utilizzati blocchi annidati. `atomic()`
  + GORM quando viene usato`Savepoint`.
  + pSQLodbc quando l'impostazione del livello di rollback è impostata sul rollback a livello di istruzione (ad esempio,). `PROTOCOL=7.4-2`
+ Carichi di **lavoro simultanei elevati con transazioni e sottotransazioni di lunga durata — Quando si verifica un overflow SLRU di sottotransazioni** durante carichi di lavoro simultanei elevati e transazioni e sottotransazioni di lunga durata, PostgreSQL sperimenta un aumento della contesa. Ciò si manifesta con eventi di attesa e blocchi elevati. `LWLock:SubtransBuffer` `LWLock:SubtransSLRU`

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

Consigliamo azioni diverse a seconda delle cause dell’evento di attesa. Alcune azioni forniscono un sollievo immediato, mentre altre richiedono indagini e correzioni a lungo termine.

**Topics**
+ [Monitoraggio dell'utilizzo delle sottotransazioni](#wait-event.lwlocksubtransslru.actions.monitor)
+ [Configurazione dei parametri di memoria](#wait-event.lwlocksubtransslru.actions.memory)
+ [Long-term azioni](#wait-event.lwlocksubtransslru.actions.longterm)

### Monitoraggio dell'utilizzo delle sottotransazioni
<a name="wait-event.lwlocksubtransslru.actions.monitor"></a>

Per le versioni 16.1 e successive di PostgreSQL, usa la seguente query per monitorare il conteggio delle sottotransazioni e lo stato di overflow per backend. Questa query unisce le statistiche di backend con le informazioni sulle attività per mostrare quali processi utilizzano sottotransazioni:

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

Per le versioni 13.3 e successive di PostgreSQL, monitora `pg_stat_slru` la visualizzazione per verificare la pressione della cache delle sottotransazioni. La seguente query SQL recupera le statistiche della cache SLRU per il componente Subtrans:

```
SELECT * FROM pg_stat_slru WHERE name = 'Subtrans';
```

Un `blks_read` valore in costante aumento indica un accesso frequente al disco per le sottotransazioni non memorizzate nella cache, segnalando una potenziale pressione sulla cache SLRU.

### Configurazione dei parametri di memoria
<a name="wait-event.lwlocksubtransslru.actions.memory"></a>

Per PostgreSQL 17.1 e versioni successive, è possibile configurare la dimensione della cache SLRU della sottotransazione utilizzando il parametro. `subtransaction_buffers` L'esempio di configurazione seguente mostra come impostare il parametro del buffer delle sottotransazioni:

```
subtransaction_buffers = 128
```

Questo parametro specifica la quantità di memoria condivisa utilizzata per memorizzare nella cache i contenuti delle sottotransazioni (). `pg_subtrans` Se specificato senza unità, il valore rappresenta blocchi di `BLCKSZ` byte, in genere 8 KB ciascuno. Ad esempio, l'impostazione del valore su 128 alloca 1 MB (128 \* 8 kB) di memoria per la cache delle sottotransazioni.

**Nota**  
È possibile impostare questo parametro a livello di cluster in modo che tutte le istanze rimangano coerenti. Verifica e modifica il valore in base ai requisiti specifici del carico di lavoro e alla classe di istanza. È necessario riavviare l'istanza di writer per rendere effettive le modifiche ai parametri.

### Long-term azioni
<a name="wait-event.lwlocksubtransslru.actions.longterm"></a>
+ **Esamina il codice e le configurazioni dell'applicazione**: esamina le configurazioni del codice dell'applicazione e dei driver del database per l'utilizzo esplicito e implicito e `SAVEPOINT` l'utilizzo delle sottotransazioni in generale. Identifica le transazioni che potrebbero generare più di 64 sottotransazioni.
+ **Riduci l'utilizzo dei savepoint**: riduci al minimo l'uso dei savepoint nelle transazioni:
  + Rivedi PL/pgSQL le procedure e le funzioni con i blocchi EXCEPTION. I blocchi EXCEPTION creano automaticamente punti di salvataggio impliciti, che possono contribuire all'overflow delle sottotransazioni. Ogni clausola EXCEPTION crea una sottotransazione, indipendentemente dal fatto che si verifichi effettivamente un'eccezione durante l'esecuzione.  
**Example**  

    Esempio 1: utilizzo problematico del blocco EXCEPTION

    Il seguente esempio di codice mostra l'utilizzo problematico del blocco EXCEPTION che crea più sottotransazioni:

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

    Il seguente esempio di codice migliorato riduce l'utilizzo delle sottotransazioni utilizzando UPSERT anziché la gestione delle eccezioni:

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

    Esempio 2: gestore di eccezioni STRICT

    Il seguente esempio di codice mostra la gestione problematica delle ECCEZIONI con 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;
    ```

    Il seguente esempio di codice migliorato evita le sottotransazioni utilizzando IF NOT FOUND anziché la gestione delle eccezioni:

    ```
    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;
    ```
  + Driver JDBC: il `autosave` parametro, se impostato su `always` o`conservative`, genera punti di salvataggio prima di ogni query. Valuta se l'`never`impostazione è accettabile per la tua applicazione.
  + Driver ODBC PostgreSQL (pSQLOdBC): l'impostazione del livello di rollback (per il rollback a livello di istruzione) crea punti di salvataggio impliciti per abilitare la funzionalità di rollback delle istruzioni. Valuta se il rollback a livello di transazione o nessun rollback è accettabile per la tua applicazione. 
  + Esamina le configurazioni delle transazioni ORM
  + Prendi in considerazione strategie alternative di gestione degli errori che non richiedono punti di salvataggio
+ **Ottimizza la progettazione delle transazioni**: ristruttura le transazioni per evitare un annidamento eccessivo e ridurre la probabilità che si verifichino condizioni di overflow delle sottotransazioni.
+ **Riduzione delle transazioni di lunga durata: le transazioni** possono aggravare i problemi relativi alle Long-running sottotransazioni conservando più a lungo le informazioni relative alle sottotransazioni. Monitora le metriche di Performance Insights e configura il `idle_in_transaction_session_timeout` parametro per terminare automaticamente le transazioni inattive.
+ Monitora le metriche di Performance Insights: monitora le metriche tra cui `idle_in_transaction_count` (numero di sessioni inattive nello stato della transazione) e `idle_in_transaction_max_time` (durata della transazione inattiva più lunga) per rilevare le transazioni di lunga durata.
+ Configura`idle_in_transaction_session_timeout`: imposta questo parametro nel tuo gruppo di parametri per terminare automaticamente le transazioni inattive dopo una durata specificata.
+ Monitoraggio proattivo: monitora gli eventi più frequenti `LWLock:SubtransBuffer` e `LWLock:SubtransSLRU` attendi gli eventi per rilevare le controversie relative alle sottotransazioni prima che diventino critiche.