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
Les événements LWLock:SubtransSLRU and LWLock:SubtransBuffer wait indiquent qu'une session attend d'accéder au cache simple le moins récemment utilisé (SLRU) 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 simple le moins récemment utilisé (SLRU) pour une sous-transaction. Dans RDS pour PostgreSQL 12.22 et versions antérieures, cet événement d'attente est appelé.SubtransControlLock -
LWLock:SubtransBuffer: Un processus attend I/O une sous-transaction dans une mémoire tampon simple la moins récemment utilisée (SLRU). Dans RDS pour PostgreSQL 12.22 et versions antérieures, cet événement d'attente est 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 d' 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 sur la gestion des transactions.
Détails de mise en œuvre — PostgreSQL implémente les sous-transactions sous forme de structures imbriquées dans les transactions principales. Chaque sous-transaction reçoit son propre identifiant de transaction.
Principaux aspects de la mise en œuvre :
-
IDs Les transactions sont suivies dans
pg_xact -
Les relations parent-enfant sont stockées dans
pg_subtransle sous-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 d'accéder au cache simple utilisé le moins récemment (SLRU) pour les informations relatives aux sous-transactions
Causes probables de l’augmentation du nombre d’événements d’attente
Les causes courantes de contention du SLRU lié aux sous-transactions sont les suivantes :
-
Utilisation excessive de SAVEPOINT et de gestion 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. ChacuneSAVEPOINTinitie 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 de 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 lorsqu'il
Savepointest utilisé. -
PSQLodBC lorsque le paramètre de niveau d'annulation est défini sur Annulation au niveau de l'instruction (par exemple,).
PROTOCOL=7.4-2
-
-
Charges de travail simultanées élevées associées à des transactions et sous-transactions de longue durée : lorsque le nombre de sous-transactions SLRU déborde lors de charges de travail simultanées élevées et de transactions et sous-transactions de longue durée, PostgreSQL est confronté à une augmentation des contentions. Cela se traduit par des temps d'attente élevés
LWLock:SubtransBufferet desLWLock:SubtransSLRUblocages.
Actions
Nous vous recommandons différentes actions en fonction des causes de votre événement d’attente. Certaines actions 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épassements 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 vue pour détecter la pression pg_stat_slru 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 augmentation constante indique un accès fréquent au disque pour les sous-transactions non mises en cache, ce qui indique une pression potentielle sur le cache du 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 du tampon de sous-transactions :
subtransaction_buffers = 128
Ce paramètre indique 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, définir la valeur sur 128 alloue 1 Mo (128 x 8 Ko) de mémoire au cache de 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 du rédacteur pour que les modifications des paramètres soient prises en compte.
Actions à long terme
-
Examinez le code et les configurations de l'application : passez en revue les configurations du code de votre application et du pilote de base de données pour en déterminer
SAVEPOINTl'utilisation explicite et implicite et l'utilisation des sous-transactions en général. Identifiez les transactions susceptibles de générer plus de 64 sous-transactions. -
Réduisez l'utilisation des points de sauvegarde — Minimisez l'utilisation de 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épassement des sous-transactions. Chaque clause EXCEPTION crée une sous-transaction, qu'une exception se produise ou non pendant l'exécution.
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 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. Évaluez si leneverparamètre est acceptable pour votre application. -
Pilote ODBC PostgreSQL (PSQLodBC) : le paramètre du niveau de restauration (pour la restauration au niveau des instructions) crée des points de sauvegarde implicites pour activer la fonctionnalité de restauration des instructions. Déterminez si une annulation au niveau de la transaction est 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éduction des transactions de longue durée — Les transactions de longue durée peuvent exacerber les problèmes de sous-transactions en conservant plus longtemps les informations relatives aux sous-transactions. Surveillez les métriques Performance Insights et configurez le
idle_in_transaction_session_timeoutparamètre pour mettre fin automatiquement aux transactions inactives. -
Surveillez les indicateurs de Performance Insights : suivez des indicateurs tels que
idle_in_transaction_count(nombre de sessions inactives dans l'é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 élevées d'événements
LWLock:SubtransBufferetLWLock:SubtransSLRUattendez afin de détecter les litiges liés aux sous-transactions avant qu'ils ne deviennent critiques.