Statistiques de transaction

Spanner fournit des tables intégrées qui stockent des statistiques sur les transactions. Vous pouvez récupérer les statistiques de ces tables SPANNER_SYS.TXN_STATS* à l'aide d'instructions SQL.

Quand utiliser les statistiques sur les transactions ?

Les statistiques sur les transactions sont utiles pour analyser les problèmes de performances. Par exemple, vous pouvez vérifier si des transactions de longue durée sont susceptibles d'affecter les performances ou le nombre de requêtes par seconde (RPS) de votre base de données. Un autre scénario se produit lorsque vos applications clientes subissent une latence élevée pour l'exécution des transactions. L'analyse des statistiques relatives aux transactions peut aider à détecter les goulots d'étranglement potentiels, tels que des volumes de mises à jour importants sur une colonne particulière, susceptibles d'impacter la latence.

Qui peut en bénéficier ?

Les données SPANNER_SYS ne sont disponibles que via des interfaces SQL. Exemple :

  • Page Spanner Studio d'une base de données dans la console Google Cloud

  • La commande gcloud spanner databases execute-sql

  • Le tableau de bord Insights sur les transactions

  • L'API executeQuery

Les autres méthodes de lecture unique fournies par Spanner ne sont pas compatibles avec SPANNER_SYS.

Statistiques de latence regroupées par transaction

Les tableaux suivants permettent d'effectuer le suivi des statistiques des transactions TOP consommant des ressources au cours d'une période donnée.

  • SPANNER_SYS.TXN_STATS_TOP_MINUTE : statistiques des transactions cumulées sur une minute.

  • SPANNER_SYS.TXN_STATS_TOP_10MINUTE : statistiques des transactions cumulées sur des intervalles de 10 minutes.

  • SPANNER_SYS.TXN_STATS_TOP_HOUR : statistiques des transactions cumulées sur une heure.

Ces tables ont les propriétés suivantes :

  • Chaque table contient les données correspondant à des intervalles de temps sans chevauchement de la durée spécifiée par le nom de la table.

  • Les intervalles sont basés sur les heures. Les intervalles d'une minute se terminent toutes les minutes, les intervalles de 10 minutes se terminent toutes les 10 minutes à partir de l'heure, et les intervalles d'une heure se terminent toutes les heures.

    Par exemple, à 11:59:30, les intervalles les plus récents disponibles pour les requêtes SQL sont les suivants :

    • 1 minute : 11:58:00 – 11:58:59
    • 10 minutes : 11:40:00 – 11:49:59
    • 1 heure : 10:00:00 – 10:59:59
  • Spanner regroupe les statistiques par FPRINT (empreinte) des transactions. Si une balise de transaction est présente, FPRINT correspond au hachage de la balise. Sinon, il s'agit du hachage calculé en fonction des opérations impliquées dans la transaction.

  • Étant donné que les statistiques sont regroupées en fonction du FPRINT, si la même transaction est exécutée plusieurs fois dans un intervalle de temps donné, ces tables n'affichent qu'une seule entrée pour cette transaction.

  • Chaque ligne contient des statistiques pour toutes les exécutions d'une transaction particulière pour laquelle Spanner enregistre des statistiques pendant l'intervalle spécifié.

Si Spanner ne peut pas stocker les statistiques de toutes les transactions exécutées pendant l'intervalle dans ces tables, le système donne la priorité aux transactions ayant la latence la plus élevée, les tentatives de commit et les octets écrits pendant l'intervalle spécifié.

Schéma de la table

Nom de la colonne Type Description
INTERVAL_END TIMESTAMP Fin de l'intervalle de temps au cours duquel les exécutions de transaction retenues ont eu lieu.
TRANSACTION_TAG STRING Tag de transaction facultatif pour cette opération de transaction. Pour en savoir plus sur l'utilisation des tags, consultez la section Dépannage à l'aide des tags de transaction. Les statistiques de plusieurs transactions ayant la même chaîne de balise sont regroupées sur une seule ligne, où "TRANSACTION_TAG" correspond à cette chaîne de balise.
FPRINT INT64 Hachage de TRANSACTION_TAG, le cas échéant. Dans le cas contraire, le hachage est calculé en fonction des opérations associées à la transaction. L'ensemble composé de INTERVAL_END et FPRINT constitue une clé unique pour ces tables.
READ_COLUMNS ARRAY<STRING> Ensemble de colonnes lues par la transaction.
WRITE_CONSTRUCTIVE_COLUMNS ARRAY<STRING> Ensemble de colonnes ayant été écrites (c'est-à-dire ayant été assignées à de nouvelles valeurs) par la transaction.

Pour les flux de modifications, si la transaction implique une écriture dans les colonnes et les tables surveillées par un flux de modifications, WRITE_CONSTRUCTIVE_COLUMNS contiendra deux colonnes (.data et ._exists 1) précédées d'un nom de flux de modifications.
WRITE_DELETE_TABLES ARRAY<STRING> Ensemble de tables dont les lignes ont été supprimées ou remplacées par la transaction.
ATTEMPT_COUNT INT64 Nombre total de tentatives de la transaction, y compris les tentatives d'annulation avant d'appeler "commit".
COMMIT_ATTEMPT_COUNT INT64 Nombre total de tentatives de commit de la transaction. Il doit correspondre au nombre d'appels à la méthode commit de la transaction.
COMMIT_ABORT_COUNT INT64 Nombre total de tentatives de transaction annulées, y compris celles qui ont été annulées avant d'appeler la méthode commit de la transaction.
COMMIT_RETRY_COUNT INT64 Nombre total de tentatives effectuées à partir de tentatives précédemment annulées. Une transaction Spanner peut être essayée plusieurs fois avant son commit en raison de conflits de verrouillage ou d'événements temporaires. Un nombre élevé de tentatives par rapport au nombre de tentatives de commit indique la présence de problèmes nécessitant d'être examinés. Pour en savoir plus, consultez la section Comprendre les transactions et le nombre de commits sur cette page.
COMMIT_FAILED_PRECONDITION_COUNT INT64 Nombre total de tentatives de validation de transaction ayant renvoyé des erreurs de condition préalable ayant échoué, telles que des cas de non-respect des index UNIQUE, une ligne déjà existante, une ligne introuvable, etc.
AVG_PARTICIPANTS FLOAT64 Nombre moyen de participants à chaque tentative de commit. Pour en savoir plus sur les participants, consultez la page Déroulement des opérations de lecture et d'écriture Spanner.
AVG_TOTAL_LATENCY_SECONDS FLOAT64 Nombre moyen de secondes écoulées entre la première opération de la transaction et le commit ou l'abandon.
AVG_COMMIT_LATENCY_SECONDS FLOAT64 Nombre moyen de secondes nécessaires pour effectuer l'opération de commit.
AVG_BYTES FLOAT64 Nombre moyen d'octets écrits par la transaction.
TOTAL_LATENCY_DISTRIBUTION ARRAY<STRUCT>

Un histogramme de la latence de commit totale, qui correspond au temps écoulé entre l'heure de début de la première opération transactionnelle et l'heure de commit ou d'abandon, pour toutes les tentatives d'une transaction.

Si une transaction est annulée plusieurs fois, puis comment elle est validée, la latence est mesurée pour chaque tentative jusqu'au dernier commit ayant abouti. Les valeurs sont mesurées en secondes.

Le tableau contient un seul élément et son type est le suivant :
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

Pour en savoir plus sur les valeurs, consultez Distribution.

Pour calculer la latence de centile souhaitée à partir de la distribution, utilisez la fonction SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64), qui renvoie le ne centile estimé. Pour obtenir un exemple connexe, consultez la section Trouver la latence au 99e centile pour les transactions.

Pour en savoir plus, consultez la section Centiles et métriques de valeur de distribution.

OPERATIONS_BY_TABLE ARRAY<STRUCT>

Impact des opérations INSERT ou UPDATE par transaction, par table. Cela est indiqué par le nombre de fois où les lignes sont affectées et le nombre d'octets écrits.

Cette colonne permet de visualiser la charge sur les tables et fournit des insights sur le taux d'écriture d'une transaction dans les tables.

Spécifiez le tableau comme suit :
ARRAY<STRUCT<
  TABLE STRING(MAX),
  INSERT_OR_UPDATE_COUNT INT64,
  INSERT_OR_UPDATE_BYTES INT64>>

1 _exists est un champ interne utilisé pour vérifier si une ligne existe ou non.

Exemples de requêtes

Cette section présente plusieurs exemples d'instructions SQL permettant d'extraire des statistiques sur les transactions. Vous pouvez exécuter ces instructions SQL à l'aide des bibliothèques clientes, de gcloud spanner ou de la console Google Cloud.

Répertorier les statistiques de base de chaque transaction sur une période donnée

La requête suivante renvoie les données brutes correspondant aux principales transactions exécutées au cours de la minute précédente.

SELECT fprint,
       read_columns,
       write_constructive_columns,
       write_delete_tables,
       avg_total_latency_seconds,
       avg_commit_latency_seconds,
       operations_by_table,
       avg_bytes
FROM spanner_sys.txn_stats_top_minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.txn_stats_top_minute);
Sortie de la requête
fprint read_columns write_constructive_columns write_delete_tables avg_total_latency_seconds avg_commit_latency_seconds operations_by_table avg_bytes
40015598317 [] ["Routes.name", "Cars.model"] ["Users"] 0.006578737 0.006547737 [["Cars",1107,30996],["Routes",560,26880]] 25286
20524969030 ["id", "no"] [] [] 0.001732442 0.000247442 [] 0
77848338483 [] [] ["Cars", "Routes"] 0.033467418 0.000251418 [] 0

Répertorier les transactions avec la latence de commit moyenne la plus élevée

La requête suivante renvoie les transactions avec une latence de commit moyenne élevée au cours de l'heure précédente, triées de la latence de commit moyenne la plus élevée à la plus faible.

SELECT fprint,
       read_columns,
       write_constructive_columns,
       write_delete_tables,
       avg_total_latency_seconds,
       avg_commit_latency_seconds,
       avg_bytes
FROM spanner_sys.txn_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.txn_stats_top_hour)
ORDER BY avg_commit_latency_seconds DESC;
Sortie de la requête
fprint read_columns write_constructive_columns write_delete_tables avg_total_latency_seconds avg_commit_latency_seconds avg_bytes
40015598317 [] ["Routes.name", "Cars.model"] ["Users"] 0.006578737 0.006547737 25286
77848338483 [] [] ["Cars", "Routes"] 0.033467418 0.000251418 0
20524969030 ["id", "no"] [] [] 0.001732442 0.000247442 0

Trouver la latence moyenne des transactions lisant certaines colonnes

La requête suivante renvoie les informations de latence moyenne pour les transactions qui lisent la colonne ADDRESS à partir des statistiques de l'heure précédente :

SELECT fprint,
       read_columns,
       write_constructive_columns,
       write_delete_tables,
       avg_total_latency_seconds
FROM spanner_sys.txn_stats_top_hour
WHERE 'ADDRESS' IN UNNEST(read_columns)
ORDER BY avg_total_latency_seconds DESC;
Sortie de la requête
fprint read_columns write_constructive_columns write_delete_tables avg_total_latency_seconds
77848338483 ["ID", "ADDRESS"] [] ["Cars", "Routes"] 0.033467418
40015598317 ["ID", "NAME", "ADDRESS"] [] ["Users"] 0.006578737

Lister les transactions en fonction du nombre moyen d'octets modifiés

La requête suivante renvoie les transactions échantillonnées au cours de l'heure précédente, triées suivant le nombre moyen d'octets modifiés par la transaction.

SELECT fprint,
       read_columns,
       write_constructive_columns,
       write_delete_tables,
       avg_bytes
FROM spanner_sys.txn_stats_top_hour
ORDER BY avg_bytes DESC;
Sortie de la requête
fprint read_columns write_constructive_columns write_delete_tables avg_bytes
40015598317 [] [] ["Users"] 25286
77848338483 [] [] ["Cars", "Routes"] 12005
20524969030 ["ID", "ADDRESS"] [] ["Users"] 10923

Statistiques globales

SPANNER_SYS contient également des tables permettant de stocker les données globales de toutes les transactions pour lesquelles Spanner a capturé des statistiques sur une période spécifique:

  • SPANNER_SYS.TXN_STATS_TOTAL_MINUTE : statistiques globales pour toutes les transactions effectuées toutes les minutes
  • SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE : statistiques globales pour toutes les transactions effectuées durant des intervalles de 10 minutes
  • SPANNER_SYS.TXN_STATS_TOTAL_HOUR : statistiques globales pour toutes les transactions effectuées toutes les heures

Les tableaux de statistiques globales présentent les propriétés suivantes :

  • Chaque table contient les données correspondant à des intervalles de temps sans chevauchement de la durée spécifiée par le nom de la table.

  • Les intervalles sont définis selon l'heure réelle. Les intervalles d'une minute se terminent toutes les minutes, les intervalles de 10 minutes se terminent toutes les 10 minutes à partir de l'heure et les intervalles d'une heure se terminent toutes les heures.

    Par exemple, à 11:59:30, les intervalles les plus récents disponibles pour les requêtes SQL sur les statistiques de transaction globales sont les suivants :

    • 1 minute : 11:58:00 – 11:58:59
    • 10 minutes : 11:40:00 – 11:49:59
    • 1 heure : 10:00:00 – 10:59:59
  • Chaque ligne contient les statistiques globales correspondant à l'ensemble des transactions exécutées sur la base de données au cours de l'intervalle spécifié. Il n'y a par conséquent qu'une seule ligne par intervalle de temps.

  • Les statistiques capturées dans les tables SPANNER_SYS.TXN_STATS_TOTAL_* peuvent inclure des transactions que Spanner n'a pas capturées dans les tables SPANNER_SYS.TXN_STATS_TOP_*.

  • Certaines colonnes de ces tables sont exposées sous forme de métriques dans Cloud Monitoring. Les métriques exposées sont les suivantes:

    • Nombre de tentatives de commit
    • Nombre de tentatives de commit
    • Participants aux transactions
    • Latences des transactions
    • Octets écrits

    Pour en savoir plus, consultez la page Métriques Spanner.

Schéma de la table

Nom de la colonne Type Description
INTERVAL_END TIMESTAMP Fin de l'intervalle de temps au cours duquel cette statistique a été capturée.
ATTEMPT_COUNT INT64 Nombre total de tentatives de transactions, y compris les tentatives d'annulation avant d'appeler "commit".
COMMIT_ATTEMPT_COUNT INT64 Nombre total de tentatives de commit de la transaction. Il doit correspondre au nombre d'appels à la méthode commit de la transaction.
COMMIT_ABORT_COUNT INT64 Nombre total de tentatives de transaction annulées, y compris celles qui ont été annulées avant d'appeler la méthode commit de la transaction.
COMMIT_RETRY_COUNT INT64 Nombre de tentatives de commit correspondant à des tentatives précédemment annulées. Une transaction Spanner peut avoir été essayée plusieurs fois avant son commit en raison de conflits de verrouillage ou d'événements temporaires. Un nombre élevé de tentatives par rapport au nombre de tentatives de commit indique la présence de problèmes nécessitant d'être examinés. Pour en savoir plus, consultez la section Comprendre les transactions et le nombre de commits sur cette page.
COMMIT_FAILED_PRECONDITION_COUNT INT64 Nombre total de tentatives de validation de transaction ayant renvoyé des erreurs de condition préalable ayant échoué, telles que des cas de non-respect des index UNIQUE, une ligne déjà existante, une ligne introuvable, etc.
AVG_PARTICIPANTS FLOAT64 Nombre moyen de participants à chaque tentative de commit. Pour en savoir plus sur les participants, consultez la page Déroulement des opérations de lecture et d'écriture Spanner.
AVG_TOTAL_LATENCY_SECONDS FLOAT64 Nombre moyen de secondes écoulées entre la première opération de la transaction et le commit ou l'abandon.
AVG_COMMIT_LATENCY_SECONDS FLOAT64 Nombre moyen de secondes nécessaires pour effectuer l'opération de commit.
AVG_BYTES FLOAT64 Nombre moyen d'octets écrits par la transaction.
TOTAL_LATENCY_DISTRIBUTION ARRAY<STRUCT>

Histogramme de la latence de commit totale, qui correspond au temps écoulé entre l'heure de début de la première opération transactionnelle et l'heure de commit ou d'abandon pour toutes les tentatives de transaction.

Si une transaction est annulée plusieurs fois, puis comment elle est validée, la latence est mesurée pour chaque tentative jusqu'au dernier commit ayant abouti. Les valeurs sont mesurées en secondes.

Le tableau contient un seul élément et son type est le suivant :
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

Pour en savoir plus sur les valeurs, consultez Distribution.

Pour calculer la latence de centile souhaitée à partir de la distribution, utilisez la fonction SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64), qui renvoie le ne centile estimé. Vous trouverez un exemple dans la section Trouver la latence au 99e centile pour les transactions.

Pour en savoir plus, consultez la section Centiles et métriques de valeur de distribution.

OPERATIONS_BY_TABLE ARRAY<STRUCT>

Impact des opérations INSERT ou UPDATE sur toutes les transactions, par table. Cela est indiqué par le nombre de fois où les lignes sont affectées et le nombre d'octets écrits.

Cette colonne permet de visualiser la charge sur les tables et fournit des insights sur le taux d'écriture des transactions dans les tables.

Spécifiez le tableau comme suit :
ARRAY<STRUCT<
  TABLE STRING(MAX),
  INSERT_OR_UPDATE_COUNT INT64,
  INSERT_OR_UPDATE_BYTES INT64>>

Exemples de requêtes

Cette section présente plusieurs exemples d'instructions SQL permettant d'extraire des statistiques sur les transactions. Vous pouvez exécuter ces instructions SQL à l'aide des bibliothèques clientes, de gcloud spanner ou de la console Google Cloud.

Trouver le nombre total de tentatives de commit d'une transaction

La requête suivante renvoie le nombre total de tentatives de commit pour toutes les transactions au cours de la dernière minute complète :

SELECT interval_end,
       commit_attempt_count
FROM spanner_sys.txn_stats_total_minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.txn_stats_total_minute)
ORDER BY interval_end;
Sortie de la requête
interval_end commit_attempt_count
2020-01-17 11:46:00-08:00 21

Notez qu'il n'y a qu'une ligne dans le résultat, car les statistiques agrégées ne comportent qu'une seule entrée par interval_end pour une durée donnée.

Déterminer la latence totale de commit de toutes les transactions

La requête suivante renvoie la latence de commit totale pour toutes les transactions au cours des 10 dernières minutes :

SELECT (avg_commit_latency_seconds * commit_attempt_count / 60 / 60)
  AS total_commit_latency_hours
FROM spanner_sys.txn_stats_total_10minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.txn_stats_total_10minute);
Sortie de la requête
total_commit_latency_hours
0.8967

Notez qu'il n'y a qu'une ligne dans le résultat, car les statistiques agrégées ne comportent qu'une seule entrée par interval_end pour une durée donnée.

Trouver la latence au 99e centile pour les transactions

La requête suivante renvoie la latence au 99e centile pour les transactions exécutées au cours des 10 dernières minutes:

SELECT interval_end, avg_total_latency_seconds,
       SPANNER_SYS.DISTRIBUTION_PERCENTILE(total_latency_distribution[OFFSET(0)], 99.0)
  AS percentile_latency
FROM spanner_sys.txn_stats_total_10minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.txn_stats_total_10minute)
ORDER BY interval_end;

Sortie de la requête
interval_end avg_total_latency_seconds percentile_latency
2022-08-17 11:46:00-08:00 0.34576998305986395 9.00296190476190476

Notez la différence importante entre la latence moyenne et la latence au 99e centile. La latence du 99e centile permet d'identifier d'éventuelles transactions aberrantes avec une latence élevée.

Le résultat ne contient qu'une seule ligne, car les statistiques agrégées ne comportent qu'une entrée par interval_end pour n'importe quelle durée.

Conservation des données

Spanner conserve au minimum les données de chaque table pour les périodes suivantes:

  • SPANNER_SYS.TXN_STATS_TOP_MINUTE et SPANNER_SYS.TXN_STATS_TOTAL_MINUTE : intervalles couvrant les six heures précédentes

  • SPANNER_SYS.TXN_STATS_TOP_10MINUTE et SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE : intervalles couvrant les quatre derniers jours.

  • SPANNER_SYS.TXN_STATS_TOP_HOUR et SPANNER_SYS.TXN_STATS_TOTAL_HOUR : intervalles couvrant les 30 derniers jours.

Les statistiques de transaction dans Spanner fournissent des informations sur la manière dont une application utilise la base de données et sont utiles lors de l'examen des problèmes de performances. Par exemple, vous pouvez vérifier si des transactions de longue durée sont susceptibles d'entraîner des conflits, ou identifier des sources potentielles de charge élevée, telles que des volumes de mises à jour importants sur une colonne particulière. Les étapes ci-dessous vous montreront comment utiliser les statistiques de transaction pour étudier les situations de contention au sein de votre base de données.

Comprendre les transactions et le nombre de commits

Vous devrez peut-être essayer plusieurs fois une transaction Spanner avant son commit. Cela se produit le plus souvent lorsque deux transactions tentent de travailler sur les mêmes données en même temps et que l'une des transactions doit être annulée pour préserver la propriété d'isolation de la transaction. Voici d'autres événements temporaires qui peuvent également entraîner l'annulation d'une transaction:

  • Problèmes de réseau temporaires.

  • Modifications du schéma de base de données appliquées pendant qu'une transaction est en cours de validation.

  • L'instance Spanner n'a pas la capacité de gérer toutes les requêtes qu'elle reçoit.

Dans de tels scénarios, un client doit relancer la transaction annulée jusqu'à ce qu'elle soit validée ou expire. Pour les utilisateurs des bibliothèques clientes officielles de Spanner, chaque bibliothèque a mis en place un mécanisme de nouvelle tentative automatique. Si vous utilisez une version personnalisée du code client, encapsulez les commits de vos transactions dans une boucle de nouvelle tentative.

Une transaction Spanner peut également être annulée en raison d'une erreur non récupérable, telle qu'un délai avant expiration de la transaction, des problèmes d'autorisation ou un nom de table/colonne non valide. Il n'est pas nécessaire de relancer ces transactions, et la bibliothèque cliente Spanner renvoie immédiatement l'erreur.

Le tableau suivant décrit plusieurs exemples de journalisation de COMMIT_ATTEMPT_COUNT, COMMIT_ABORT_COUNT et COMMIT_RETRY_COUNT dans différents scénarios.

Scénario COMMIT_ATTEMPT_COUNT COMMIT_ABORT_COUNT COMMIT_RETRY_COUNT
La transaction a bien été validée à la première tentative. 1 0 0
Transaction annulée en raison d'une erreur de délai d'inactivité. 1 1 0
Transaction annulée en raison d'un problème réseau temporaire et validée après une nouvelle tentative. 2 1 1
Cinq transactions ayant la même FPRINT sont exécutées dans un intervalle de 10 minutes. Trois transactions ont été validées lors de la première tentative, tandis que deux ont été annulées, puis validées lors de la première tentative. 7 2 2

Les données des tables de statistiques de transactions sont des données agrégées pour un intervalle de temps donné. Pour un intervalle particulier, il est possible qu'une transaction soit annulée et relancée autour des limites et qu'elle tombe dans des buckets différents. Par conséquent, les abandons et les nouvelles tentatives peuvent être différents pour un intervalle de temps donné.

Ces statistiques sont conçues pour le dépannage et l'introspection. Leur précision à 100% n'est pas garantie. Les statistiques sont agrégées en mémoire avant d'être stockées dans des tables Spanner. Lors d'une mise à niveau ou d'une autre activité de maintenance, les serveurs Spanner peuvent redémarrer, ce qui affecte la précision des chiffres.

Résoudre les conflits de base de données à l'aide des statistiques de transaction

Vous pouvez utiliser le code SQL ou le tableau de bord Informations sur les transactions pour afficher les transactions de votre base de données qui peuvent entraîner des latences élevées en raison de conflits de verrouillage.

Les rubriques suivantes expliquent comment examiner ces transactions à l'aide du code SQL.

Sélectionnez une période à examiner

Vous le trouverez dans l'application qui utilise Spanner.

Pour les besoins de cet exercice, imaginons que le problème a commencé vers 17h20 le 17 mai 2020.

Vous pouvez utiliser des tags de transaction pour identifier la source de la transaction, et corréler entre les tables de statistiques des transactions et les tables de statistiques de verrouillage pour résoudre efficacement les conflits de verrouillage. Pour en savoir plus, consultez Résoudre les problèmes liés aux tags de transaction.

Recueillir des statistiques sur les transactions pour la période sélectionnée

Pour commencer notre enquête, nous allons interroger la table TXN_STATS_TOTAL_10MINUTE sur la période correspondant au début du problème. Les résultats de cette requête nous indiqueront comment ont évolué la latence et autres statistiques sur les transactions au cours de cette période.

Par exemple, la requête suivante renvoie les statistiques de transaction agrégées de 4:30 pm à 7:40 pm (inclus).

SELECT
  interval_end,
  ROUND(avg_total_latency_seconds,4) as avg_total_latency_seconds,
  commit_attempt_count,
  commit_abort_count
FROM SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE
WHERE
  interval_end >= "2020-05-17T16:40:00"
  AND interval_end <= "2020-05-17T19:40:00"
ORDER BY interval_end;

Le tableau suivant répertorie les données d'exemple renvoyées par notre requête.

interval_end avg_total_latency_seconds commit_attempt_count commit_abort_count
2020-05-17 16:40:00-07:00 0,0284 315691 5170
2020-05-17 16:50:00-07:00 0,0250 302124 3828
2020-05-17 17:00:00-07:00 0,0460 346087 11382
2020-05-17 17:10:00-07:00 0,0864 379964 33826
2020-05-17 17:20:00-07:00 0,1291 390343 52549
2020-05-17 17:30:00-07:00 0,1314 456455 76392
2020-05-17 17:40:00-07:00 0,1598 507774 121458
2020-05-17 17:50:00-07:00 0,1641 516587 115875
2020-05-17 18:00:00-07:00 0,1578 552711 122626
2020-05-17 18:10:00-07:00 0,1750 569460 154205
2020-05-17 18:20:00-07:00 0,1727 613571 160772
2020-05-17 18:30:00-07:00 0,1588 601994 143044
2020-05-17 18:40:00-07:00 0,2025 604211 170019
2020-05-17 18:50:00-07:00 0,1615 601622 135601
2020-05-17 19:00:00-07:00 0,1653 596804 129511
2020-05-17 19:10:00-07:00 0,1414 560023 112247
2020-05-17 19:20:00-07:00 0,1367 570864 100596
2020-05-17 19:30:00-07:00 0,0894 539729 65316
2020-05-17 19:40:00-07:00 0,0820 479151 40398

Ici, nous voyons que la latence agrégée et le nombre d'abandons sont plus élevés dans les périodes mises en surbrillance. Nous pouvons choisir n'importe quel intervalle de 10 minutes durant lequel la latence agrégée et/ou le nombre d'abandons sont élevés. Nous allons choisir l'intervalle qui se termine à 2020-05-17T18:40:00 et l'utiliser lors de l'étape suivante pour identifier les transactions contribuant à une latence élevée et à un abandon.

Identifier les transactions qui subissent une latence élevée

Nous allons maintenant interroger la table TXN_STATS_TOP_10MINUTE dans l'intervalle sélectionné à l'étape précédente. À l'aide de ces informations, nous pouvons commencer à identifier les transactions qui présentent une latence élevée et/ou un nombre d'abandons élevé.

Exécutez la requête suivante pour obtenir les principales transactions ayant un impact sur les performances, par ordre décroissant de latence totale pour notre exemple d'intervalle se terminant à 2020-05-17T18:40:00.

SELECT
  interval_end,
  fprint,
  ROUND(avg_total_latency_seconds,4) as avg_total_latency_seconds,
  ROUND(avg_commit_latency_seconds,4) as avg_commit_latency_seconds,
  commit_attempt_count,
  commit_abort_count,
  commit_retry_count
FROM SPANNER_SYS.TXN_STATS_TOP_10MINUTE
WHERE
  interval_end = "2020-05-17T18:40:00"
ORDER BY avg_total_latency_seconds DESC;
interval_end fprint avg_total_latency_seconds avg_commit_latency_seconds commit_attempt_count commit_abort_count commit_retry_count
2020-05-17 18:40:00-07:00 15185072816865185658 0,3508 0,0139 278802 142205 129884
2020-05-17 18:40:00-07:00 15435530087434255496 0,1633 0,0142 129012 27177 24559
2020-05-17 18:40:00-07:00 14175643543447671202 0,1423 0,0133 5357 636 433
2020-05-17 18:40:00-07:00 898069986622520747 0,0198 0,0158 6 0 0
2020-05-17 18:40:00-07:00 10510121182038036893 0,0168 0,0125 7 0 0
2020-05-17 18:40:00-07:00 9287748709638024175 0,0159 0,0118 4269 1 0
2020-05-17 18:40:00-07:00 7129109266372596045 0,0142 0,0102 182227 0 0
2020-05-17 18:40:00-07:00 15630228555662391800 0,0120 0,0107 58 0 0
2020-05-17 18:40:00-07:00 7907238229716746451 0,0108 0,0097 65 0 0
2020-05-17 18:40:00-07:00 10158167220149989178 0,0095 0,0047 3454 0 0
2020-05-17 18:40:00-07:00 9353100217060788102 0,0093 0,0045 725 0 0
2020-05-17 18:40:00-07:00 9521689070912159706 0,0093 0,0045 164 0 0
2020-05-17 18:40:00-07:00 11079878968512225881 0,0064 0,0019 65 0 0

Nous pouvons constater clairement que la première ligne (mise en surbrillance) du tableau précédent montre une transaction présentant une latence élevée en raison d'un nombre élevé d'abandons de commit. Nous constatons également un nombre élevé de tentatives de validation, ce qui indique que les commits annulés ont par la suite fait l'objet d'une nouvelle tentative. À l'étape suivante, nous allons étudier plus en détail pour trouver la cause de ce problème.

Identifier les colonnes impliquées dans une transaction présentant une latence élevée

Au cours de cette étape, nous allons vérifier si les transactions à latence élevée travaillent sur le même ensemble de colonnes en récupérant les données read_columns, write_constructive_columns et write_delete_tables pour les transactions présentant un nombre élevé d'abandons. La valeur FPRINT sera également utile à l'étape suivante.

SELECT
  fprint,
  read_columns,
  write_constructive_columns,
  write_delete_tables
FROM SPANNER_SYS.TXN_STATS_TOP_10MINUTE
WHERE
  interval_end = "2020-05-17T18:40:00"
ORDER BY avg_total_latency_seconds DESC LIMIT 3;
fprint read_columns write_constructive_columns write_delete_tables
15185072816865185658 [TestHigherLatency._exists,TestHigherLatency.lang_status,TestHigherLatency.score,globalTagAffinity.shares] [TestHigherLatency._exists,TestHigherLatency.shares,TestHigherLatency_lang_status_score_index.shares] []
15435530087434255496 [TestHigherLatency._exists,TestHigherLatency.lang_status,TestHigherLatency.likes,globalTagAffinity.score] [TestHigherLatency._exists,TestHigherLatency.likes,TestHigherLatency_lang_status_score_index.likes] []
14175643543447671202 [TestHigherLatency._exists,TestHigherLatency.lang_status,TestHigherLatency.score,globalTagAffinity.ugcCount] [TestHigherLatency._exists,TestHigherLatency.ugcCount,TestHigherLatency_lang_status_score_index.ugcCount] []

Comme le résultat le montre dans le tableau précédent, les transactions présentant la latence totale moyenne la plus élevée lisent les mêmes colonnes. Nous pouvons également observer un conflit d'écriture, car les transactions écrivent dans la même colonne, à savoir TestHigherLatency._exists.

déterminer l'évolution des performances des transactions au fil du temps ;

Nous pouvons voir l'évolution des statistiques associées à cette forme de transaction au cours d'une période donnée. Utilisez la requête suivante, où $FPRINT correspond à l'empreinte de la transaction à latence élevée déterminée à l'étape précédente.

SELECT
  interval_end,
  ROUND(avg_total_latency_seconds, 3) AS latency,
  ROUND(avg_commit_latency_seconds, 3) AS commit_latency,
  commit_attempt_count,
  commit_abort_count,
  commit_retry_count,
  commit_failed_precondition_count,
  avg_bytes
FROM SPANNER_SYS.TXN_STATS_TOP_10MINUTE
WHERE
  interval_end >= "2020-05-17T16:40:00"
  AND interval_end <= "2020-05-17T19:40:00"
  AND fprint = $FPRINT
ORDER BY interval_end;
interval_end latence commit_latency commit_attempt_count commit_abort_count commit_retry_count commit_failed_precondition_count avg_bytes
2020-05-17 16:40:00-07:00 0,095 0,010 53230 4752 4330 0 91
2020-05-17 16:50:00-07:00 0,069 0,009 61264 3589 3364 0 91
2020-05-17 17:00:00-07:00 0,150 0,010 75868 10557 9322 0 91
2020-05-17 17:10:00-07:00 0,248 0,013 103151 30220 28483 0 91
2020-05-17 17:20:00-07:00 0,310 0,012 130078 45655 41966 0 91
2020-05-17 17:30:00-07:00 0,294 0,012 160064 64930 59933 0 91
2020-05-17 17:40:00-07:00 0,315 0,013 209614 104949 96770 0 91
2020-05-17 17:50:00-07:00 0,322 0,012 215682 100408 95867 0 90
2020-05-17 18:00:00-07:00 0,310 0,012 230932 106728 99462 0 91
2020-05-17 18:10:00-07:00 0,309 0,012 259645 131049 125889 0 91
2020-05-17 18:20:00-07:00 0,315 0,013 272171 137910 129411 0 90
2020-05-17 18:30:00-07:00 0,292 0,013 258944 121475 115844 0 91
2020-05-17 18:40:00-07:00 0,350 0,013 278802 142205 134229 0 91
2020-05-17 18:50:00-07:00 0,302 0,013 256259 115626 109756 0 91
2020-05-17 19:00:00-07:00 0,315 0.014 250560 110662 100322 0 91
2020-05-17 19:10:00-07:00 0,271 0.014 238384 99025 90187 0 91
2020-05-17 19:20:00-07:00 0,273 0.014 219687 84019 79874 0 91
2020-05-17 19:30:00-07:00 0.198 0,013 195357 59370 55909 0 91
2020-05-17 19:40:00-07:00 0,181 0,013 167514 35705 32885 0 91

Dans le résultat ci-dessus, nous pouvons constater que la latence totale est élevée pour la période mise en surbrillance. De plus, si la latence totale est élevée, commit_attempt_count, commit_abort_count et commit_retry_count sont également élevés même si la latence de commit (commit_latency) n'a guère changé. Étant donné que les commits de transactions sont annulés plus fréquemment, le nombre de tentatives de commit est également élevé en raison des nouvelles tentatives de commit.

Conclusion

Dans cet exemple, nous avons constaté qu'un nombre élevé d'abandons de commit était la cause d'une latence élevée. L'étape suivante consiste à examiner les messages d'erreur associés aux abandons de commit et reçus par l'application afin de connaître la raison de ces abandons. En inspectant les journaux de l'application, nous constatons que, dans les faits, celle-ci a connu une modification de sa charge de travail durant cette période, c'est-à-dire qu'une autre forme de transaction est apparue avec un nombre élevé de attempts_per_second. Cette transaction différente (par exemple une tâche de nettoyage nocturne) est responsable des conflits de verrouillage supplémentaires.

Identifier les transactions n'ayant pas fait l'objet d'une nouvelle tentative correctement

La requête suivante renvoie les transactions échantillonnées au cours des dix dernières minutes qui ont un nombre élevé d'abandons de commit, mais sans nouvelle tentative.

SELECT
  *
FROM (
  SELECT
    fprint,
    SUM(commit_attempt_count) AS total_commit_attempt_count,
    SUM(commit_abort_count) AS total_commit_abort_count,
    SUM(commit_retry_count) AS total_commit_retry_count
  FROM
    SPANNER_SYS.TXN_STATS_TOP_10MINUTE
  GROUP BY
    fprint )
WHERE
  total_commit_retry_count = 0
  AND total_commit_abort_count > 0
ORDER BY
  total_commit_abort_count DESC;
fprint total_commit_attempt_count total_commit_abort_count total_commit_retry_count
1557557373282541312 3367894 44232 0
5776062322886969344 13566 14 0

Nous pouvons voir que la transaction avec fprint 1557557373282541312 a été annulée 44 232 fois, mais qu'elle n'a jamais été relancée. Cela semble suspect, car le nombre d'abandons est élevé et il est peu probable que chaque abandon soit causé par une erreur non récupérable. En revanche, pour la transaction avec le fprint 5776062322886969344, elle est moins suspecte, car le nombre total d'abandons n'est pas très élevé.

La requête suivante renvoie plus de détails sur la transaction avec le fprint 1557557373282541312,y compris read_columns, write_constructive_columns et write_delete_tables. Ces informations permettent d'identifier la transaction dans le code client, où la logique de nouvelle tentative peut être examinée pour ce scénario.

SELECT
  interval_end,
  fprint,
  read_columns,
  write_constructive_columns,
  write_delete_tables,
  commit_attempt_count,
  commit_abort_count,
  commit_retry_count
FROM
  SPANNER_SYS.TXN_STATS_TOP_10MINUTE
WHERE
  fprint = 1557557373282541312
ORDER BY
  interval_end DESC;
interval_end fprint read_columns write_constructive_columns write_delete_tables commit_attempt_count commit_abort_count commit_retry_count
2021-01-27T18:30:00Z 1557557373282541312 ['Singers._exists'] ['Singers.FirstName', 'Singers.LastName', 'Singers._exists'] [] 805228 1839 0
2021-01-27T18:20:00Z 1557557373282541312 ['Singers._exists'] ['Singers.FirstName', 'Singers.LastName', 'Singers._exists'] [] 1034429 38779 0
2021-01-27T18:10:00Z 1557557373282541312 ['Singers._exists'] ['Singers.FirstName', 'Singers.LastName', 'Singers._exists'] [] 833677 2266 0
2021-01-27T18:00:00Z 1557557373282541312 ['Singers._exists'] ['Singers.FirstName', 'Singers.LastName', 'Singers._exists'] [] 694560 1348 0

Nous pouvons constater que la transaction implique une lecture de la colonne masquée Singers._exists pour vérifier l'existence d'une ligne. La transaction écrit également dans les colonnes Singers.FirstName et Singer.LastName. Ces informations peuvent vous aider à déterminer si le mécanisme de nouvelle tentative de transaction mis en œuvre dans votre bibliothèque cliente personnalisée fonctionne comme prévu.

Étapes suivantes