web-dev-qa-db-fra.com

Où est-ce que InnoDB stocke les données de transaction avant de le faire?

J'ai fait des tests en utilisant READ_COMMITTED et READ_UNCOMMITTED À la maison, en utilisant la technologie JDBC.

Je vois ça READ_UNCOMMITTED peut réellement lire des données non engagées, par ex. les données d'une transaction non encore engagée (pourraient effectuer une requête de mise à jour).

Des questions

  • Où sont stockées des données non engagées, telles qu'un READ_UNCOMMITTED La transaction peut-elle lire des données non engagées d'une autre transaction?
  • Pourquoi n'est-il pas possible pour un READ_COMMITTED Transaction pour lire des données non engagées, c'est-à-dire une "lecture sale"? Quel mécanisme applique cette restriction?
12
Shuzheng

" où les données non engagées stockées sont stockées, de sorte qu'une transaction read_ungmied puisse lire des données non engagées d'une autre transaction? "

Les nouvelles versions d'enregistrement non engagées (pk en cluster) sont traitées comme la version "actuelle" de l'enregistrement à la page. Donc, ils peuvent être stockés dans la piscine tampon et/ou dans le tablespace (par exemple Tablename.ibd). Transactions qui ont ensuite besoin de construire un instantané/une vue dans quelque chose d'autre que la lecture non engagée, doivent construire une version précédente de la ligne (suivant la liste d'historique) à l'aide des enregistrements d'annulation (stockés dans le Systemespace ). Lors de la lecture de l'enregistrement non engagé, InnoDB peut également avoir besoin de lire certains enregistrements d'index secondaires non engagés à partir du Modifier la mémoire tampon et d'appliquer avant de présenter l'enregistrement à l'utilisateur.

C'est ce comportement qui peut faire des retouches à InnoDB relativement coûteux. C'est le facteur important qui peut également conduire à des problèmes de performance potentiels à partir de transactions inutilisées de longue date qui détiennent des enregistrements mis à jour, car ces transactions bloqueront les opérations de purge et la liste d'historique des anciennes versions d'enregistrement augmente et les enregistrements d'annulation nécessaires pour reconstruire ces anciennes versions. à la demande continuera de croître. Il ralentit de nouvelles transactions qui doivent lire une version plus ancienne/engagée du dossier, car elles ont besoin de traverser une liste d'histoires plus longue et plus longue - qui est une liste liée à des annexes de l'annulation - et de faire plus de travail afin de reconstruire l'ancienne version du dossier. Donc, vous finissez par utiliser beaucoup de cycles de CPU (sans parler des primitives de verrouillage internes: Mutilex, RW_Locks, Semaphores, etc.) sur un travail visible non utilisateur qui ralentit le traitement de la requête.

Espérons que cela a du sens? :)

En tant que FYI, dans MySQL 5.7, vous pouvez déplacer l'espace de table Annuler et vous déconnecter de l'espace de table du système et faites-les automatiquement tronquer. Ils peuvent devenir assez volumineux si vous avez une longue transaction qui empêche les opérations de purge, ce qui entraîne une longueur de la liste d'histoires très longue et toujours croissante. Les avoir stockés dans l'espace de table System était la cause la plus courante d'un fichier ibdata1 énorme/croissant, qui ne peut être tronquée/rétrécie/aspirée afin de récupérer plus tard cet espace.

11
Matt Lord

Tu as demandé

où est stocké des données non engagées, de sorte qu'une transaction read_ungmied puisse lire des données non engagées d'une autre transaction?

Afin de répondre à votre question, vous devez savoir à quoi ressemble l'architecture InnoDB.

La photo suivante a été créée il y a des années par Percona CTO Vadim Tkachenko

InnoDB Architecture

Selon la documentation MySQL sur le modèle de transaction Innodb et le verrouillage

Un commit signifie que les modifications apportées à la transaction en cours sont rendues permanentes et visibles à d'autres sessions. Une instruction Rollback, d'autre part, annule toutes les modifications apportées par la transaction en cours. Les deux commissions de validation et de restauration sont relâchées tous les verrouillages innodubes définis lors de la transaction en cours.

Depuis que COMMIT ET ROLLBACK REMBISTRE VISIBILITÉ DES DONNÉES, LIRE ENGAGÉ ET LIRE MOTIF INDIQUÉ Devait s'appuyer sur des structures et des mécanismes qui enregistrent des changements.

  1. Segments de restauration/espace annuler
  2. Refaire des journaux
  3. Trous de serrures contre la ou les tableaux impliqués

Les segments de restauration et l'espace d'annulation sauraient savoir ce que les données modifiées semblaient avant que des modifications ne soient appliquées. Les journaux de Redo sauraient que les modifications doivent être modifiées pour que des données apparaissent mises à jour.

Vous avez également demandé

pourquoi n'est-il pas possible pour une transaction Lecture_Commode de lire des données non engagées, c'est-à-dire une "lecture sale"? Quel mécanisme applique cette restriction?

Les journaux de redo, les annulations et les lignes verrouillées sont entrées en jeu. Vous devez également consider à la piscine tampon InnoDb (où vous pouvez mesurer des pages sales avec innodb_max_dirty_pages_pct , innodb_buffer_pool_pages_dirty et innodb_buffer_pool_bytes_dirty ).

À la lumière de cela, la lecture commise saurait quelles données apparaissent de manière permanente. Par conséquent, il n'est pas nécessaire de rechercher des pages sales qui n'ont pas été commises. Lire commités ne serait rien de plus qu'une lecture sale qui a été commise. Lecture non engagée aurait continué de savoir quelles lignes doivent être verrouillées et ce que les journaux de redo ont été lus ou ignorés pour rendre les données visibles.

Pour bien comprendre le verrouillage des lignes pour gérer l'isolation, veuillez lire le modèle de transaction innodb et le verrouillage

4
RolandoMySQLDBA