Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
LWLock:SubtransSLRU (LWLock:SubtransControlLock)
Les événements LWLock:SubtransSLRU and LWLock:SubtransBuffer wait indiquent qu'une session attend d'accéder au cache SLRU (Simple Least-Recently Used) pour les informations relatives aux sous-transactions. Cela se produit lors de la détermination de la visibilité des transactions et des relations parent-enfant.
-
LWLock:SubtransSLRU: un processus attend d'accéder au cache SLRU (Simple Least-Recently Used) pour une sous-transaction. Dans RDS pour PostgreSQL antérieur à la version 13, cet événement d'attente était appelé.SubtransControlLock -
LWLock:SubtransBuffer: Un processus est en attente d' I/O une mémoire tampon simple la moins récemment utilisée (SLRU) pour une sous-transaction. Dans RDS pour PostgreSQL antérieur à la version 13, cet événement d'attente était appelé.subtrans
Rubriques
Versions de moteur prises en charge
Ces informations sur les événements d’attente sont prises en charge pour toutes les versions de RDS pour PostgreSQL.
Contexte
Comprendre les sous-transactions — Une sous-transaction est une transaction au sein d'une transaction dans PostgreSQL. Elle est également connue sous le nom de transaction imbriquée.
Les sous-transactions sont généralement créées lorsque vous utilisez :
-
Commandes de l’
SAVEPOINT -
Blocs d'exception (
BEGIN/EXCEPTION/END)
Les sous-transactions vous permettent d'annuler certaines parties d'une transaction sans affecter l'ensemble de la transaction. Cela vous donne un contrôle précis de la gestion des transactions.
Détails de la mise en œuvre : PostgreSQL implémente les sous-transactions sous forme de structures imbriquées dans les transactions principales. Chaque sous-transaction obtient son propre identifiant de transaction.
Principaux aspects de la mise en œuvre :
-
Les identifiants de transaction sont suivis dans
pg_xact -
Parent-child les relations sont stockées dans un
pg_subtranssous-répertoire sousPGDATA -
Chaque session de base de données peut gérer jusqu'à des
64sous-transactions actives -
Le dépassement de cette limite entraîne un débordement des sous-transactions, ce qui nécessite l'accès au cache SLRU (Simple Least-Recently Used) pour les informations relatives aux sous-transactions
Causes probables de l’augmentation du nombre d’événements d’attente
Les causes courantes de conflit entre les sous-transactions SLRU sont les suivantes :
-
Utilisation excessive de la gestion des points de sauvegarde et des exceptions : PL/pgSQL les procédures dotées de
EXCEPTIONgestionnaires créent automatiquement des points de sauvegarde implicites, que des exceptions se produisent ou non. ChacunSAVEPOINTinitie une nouvelle sous-transaction. Lorsqu'une seule transaction cumule plus de 64 sous-transactions, elle déclenche un dépassement du SLRU des sous-transactions. -
Configurations du pilote et de l'ORM :
SAVEPOINTl'utilisation peut être explicite dans le code de l'application ou implicite dans les configurations du pilote. De nombreux outils ORM et frameworks d'applications couramment utilisés prennent en charge les transactions imbriquées de manière native. Voici quelques exemples courants :-
Le paramètre du pilote JDBC
autosave, s'il est défini suralwaysouconservative, génère des points de sauvegarde avant chaque requête. -
Définitions des transactions Spring Framework lorsqu'elles sont définies sur
propagation_nested. -
Rails quand
requires_new: truec'est réglé. -
SQLAlchemy quand
session.begin_nestedest utilisé. -
Django lorsque des
atomic()blocs imbriqués sont utilisés. -
GORM quand il
Savepointest utilisé. -
PSQLodBC lorsque le réglage du niveau d'annulation est défini sur l'annulation au niveau de l'instruction (par exemple,).
PROTOCOL=7.4-2
-
-
Charges de travail simultanées élevées avec des transactions et des sous-transactions de longue durée — Lorsqu'un dépassement du SLRU des sous-transactions se produit pendant des charges de travail simultanées élevées et des transactions et sous-transactions de longue durée, PostgreSQL connaît un conflit accru. Cela se traduit par un nombre élevé d'événements d'attente
LWLock:SubtransBufferet deLWLock:SubtransSLRUblocages.
Actions
Nous vous recommandons différentes actions en fonction des causes de votre événement d’attente. Certaines mesures apportent un soulagement immédiat, tandis que d'autres nécessitent une enquête et une correction à long terme.
Rubriques
Surveillance de l'utilisation des sous-transactions
Pour les versions 16.1 et ultérieures de PostgreSQL, utilisez la requête suivante pour surveiller le nombre de sous-transactions et l'état des débordements par backend. Cette requête associe les statistiques du backend aux informations d'activité pour indiquer quels processus utilisent des sous-transactions :
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;
Pour les versions 13.3 et ultérieures de PostgreSQL, surveillez la pg_stat_slru vue pour vérifier la pression du cache des sous-transactions. La requête SQL suivante extrait les statistiques du cache SLRU pour le composant Subtrans :
SELECT * FROM pg_stat_slru WHERE name = 'Subtrans';
Une blks_read valeur en constante augmentation indique un accès fréquent au disque pour les sous-transactions non mises en cache, signalant une pression potentielle sur le cache SLRU.
Configuration des paramètres de mémoire
Pour PostgreSQL 17.1 et versions ultérieures, vous pouvez configurer la taille du cache SLRU des sous-transactions à l'aide du paramètre. subtransaction_buffers L'exemple de configuration suivant montre comment définir le paramètre de tampon de sous-transaction :
subtransaction_buffers = 128
Ce paramètre spécifie la quantité de mémoire partagée utilisée pour mettre en cache le contenu des sous-transactions (pg_subtrans). Lorsqu'elle est spécifiée sans unités, la valeur représente des blocs d'BLCKSZoctets, généralement de 8 Ko chacun. Par exemple, la définition de la valeur sur 128 alloue 1 Mo (128 * 8 Ko) de mémoire au cache des sous-transactions.
Note
Vous pouvez définir ce paramètre au niveau du cluster afin que toutes les instances restent cohérentes. Testez et ajustez la valeur en fonction de vos exigences spécifiques en matière de charge de travail et de classe d'instance. Vous devez redémarrer l'instance d'écriture pour que les modifications de paramètres soient prises en compte.
Long-term actions
-
Examinez le code et les configurations de l'application — Passez en revue les configurations de votre code d'application et de votre pilote de base de données pour une utilisation explicite et implicite et pour
SAVEPOINTl'utilisation des sous-transactions en général. Identifiez les transactions susceptibles de générer plus de 64 sous-transactions. -
Réduire l'utilisation des points de sauvegarde — Minimisez l'utilisation des points de sauvegarde dans vos transactions :
-
Passez en revue PL/pgSQL les procédures et les fonctions à l'aide de blocs EXCEPTION. Les blocs EXCEPTION créent automatiquement des points de sauvegarde implicites, ce qui peut contribuer au débordement des sous-transactions. Chaque clause EXCEPTION crée une sous-transaction, qu'une exception se produise réellement ou non pendant l'exécution.
Exemple
Exemple 1 : utilisation problématique du bloc EXCEPTION
L'exemple de code suivant montre l'utilisation problématique du bloc EXCEPTION qui crée plusieurs sous-transactions :
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;L'exemple de code amélioré suivant réduit l'utilisation des sous-transactions en utilisant UPSERT au lieu de la gestion des exceptions :
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;Exemple
Exemple 2 : gestionnaire d'exceptions STRICT
L'exemple de code suivant montre la gestion problématique des EXCEPTIONS avec 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;L'exemple de code amélioré suivant permet d'éviter les sous-transactions en utilisant IF NOT FOUND au lieu de la gestion des exceptions :
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; -
Pilote JDBC : le
autosaveparamètre, s'il est défini suralwaysouconservative, génère des points de sauvegarde avant chaque requête. Déterminez si leneverréglage est acceptable pour votre application. -
Pilote ODBC PostgreSQL (PSQLodBC) : le réglage du niveau d'annulation (pour l'annulation au niveau de l'instruction) crée des points de sauvegarde implicites pour activer la fonctionnalité d'annulation des instructions. Déterminez si une annulation au niveau de la transaction serait acceptable ou non pour votre application.
-
Examiner les configurations de transactions ORM
-
Envisagez d'autres stratégies de gestion des erreurs qui ne nécessitent pas de points de sauvegarde
-
-
Optimisez la conception des transactions — Restructurez les transactions pour éviter une imbrication excessive et réduire le risque de débordement des sous-transactions.
-
Réduisez les transactions de longue durée : les Long-running transactions peuvent exacerber les problèmes liés aux sous-transactions en conservant plus longtemps les informations relatives aux sous-transactions. Surveillez les métriques détaillées par requête et par compteur de base de données et configurez le
idle_in_transaction_session_timeoutparamètre pour mettre fin automatiquement aux transactions inactives. -
Surveillez les métriques détaillées par requête et par compteur de base de données — Suivez les métriques, notamment
idle_in_transaction_count(nombre de sessions inactives en état de transaction) etidle_in_transaction_max_time(durée de la transaction inactive la plus longue) pour détecter les transactions de longue durée. -
Configurer
idle_in_transaction_session_timeout: définissez ce paramètre dans votre groupe de paramètres pour mettre fin automatiquement aux transactions inactives après une durée spécifiée. -
Surveillance proactive : surveillez les occurrences fréquentes d'événements
LWLock:SubtransBufferetLWLock:SubtransSLRUattendez pour détecter les conflits liés aux sous-transactions avant qu'ils ne deviennent critiques.