Où InnoDB stocke-t-il les données de transaction avant de les valider?

12

J'ai fait quelques tests en utilisant READ_COMMITTEDet READ_UNCOMMITTEDà la maison, en utilisant la technologie JDBC.

Je vois que cela READ_UNCOMMITTEDpeut réellement lire des données non validées, par exemple des données d'une transaction non encore validée (pourrait effectuer une requête UPDATE).

Des questions

  • Où sont stockées les données non validées, de sorte qu'une READ_UNCOMMITTEDtransaction peut lire les données non validées d'une autre transaction?
  • Pourquoi une READ_COMMITTEDtransaction ne peut-elle pas lire des données non validées, c'est-à-dire effectuer une "lecture incorrecte"? Quel mécanisme applique cette restriction?
Shuzheng
la source

Réponses:

11

" Où sont stockées les données non validées, de sorte qu'une transaction READ_UNCOMMITTED puisse lire les données non validées d'une autre transaction? "

Les nouvelles versions d'enregistrements non validés (PK en cluster) sont traitées comme la version "actuelle" de l'enregistrement à la page. Ils peuvent donc être stockés dans le pool de tampons et / ou dans le tablespace (par exemple tablename.ibd). Les transactions qui doivent ensuite créer un instantané / vue dans autre chose que READ-UNCOMMITTED, doivent construire une version précédente de la ligne (après la liste d'historique) à l'aide des enregistrements UNDO (stockés dans l' espace disque logique système ). Lors de la lecture de l'enregistrement non validé, InnoDB peut également avoir besoin de lire certains enregistrements d'index secondaire non validés à partir du tampon de modification et de les appliquer avant de présenter l'enregistrement à l'utilisateur.

C'est ce comportement qui peut rendre les annulations dans InnoDB relativement coûteuses. C'est le gros facteur qui peut également entraîner des problèmes de performances potentiels des transactions inactives de longue durée qui contiennent des enregistrements mis à jour, car ces transactions bloqueront les opérations de purge et la liste d'historique des anciennes versions d'enregistrements s'allonge, et les enregistrements UNDO nécessaires pour reconstruire ces anciennes versions sur demande, continuera de croître. Il ralentit les nouvelles transactions qui doivent lire une version plus ancienne / validée de l'enregistrement, car elles doivent parcourir une liste d'historique de plus en plus longue - qui est une liste liée entre eux des enregistrements UNDO - et faire plus de travail afin de reconstruire l'ancienne version du dossier. Vous finissez donc par utiliser beaucoup de cycles CPU (sans parler des primitives de verrouillage internes: mutex, rw_locks, sémaphores, etc.

J'espère que cela a du sens? :)

Pour info, dans MySQL 5.7, vous pouvez déplacer l'espace de table UNDO et vous déconnecter de l'espace de table système et les faire tronquer automatiquement. Ils peuvent devenir assez importants si vous avez une transaction de longue durée qui empêche les opérations de purge, ce qui entraîne une longueur de liste d'historique très longue et toujours croissante. Les avoir stockés dans l'espace disque logique du système était la cause la plus courante d'un fichier ibdata1 énorme / croissant, qui à son tour ne peut pas être tronqué / réduit / aspiré afin de récupérer plus tard cet espace.

Matt Lord
la source
4

Tu as demandé

où sont stockées les données non validées, de sorte qu'une transaction READ_UNCOMMITTED puisse lire les données non validées d'une autre transaction?

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

L'image suivante a été créée il y a des années par Percona CTO Vadim Tkachenko

Architecture InnoDB

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

Un COMMIT signifie que les modifications apportées à la transaction en cours deviennent permanentes et deviennent visibles pour les autres sessions. Une instruction ROLLBACK, en revanche, annule toutes les modifications apportées par la transaction en cours. COMMIT et ROLLBACK libèrent tous les verrous InnoDB définis lors de la transaction en cours.

Étant donné que COMMIT et ROLLBACK régissent la visibilité des données, READ COMMITTED et READ UNCOMMITTED devraient s'appuyer sur des structures et des mécanismes qui enregistrent les modifications.

  1. Segments de restauration / espace d'annulation
  2. Rétablir les journaux
  3. Lacunes par rapport aux tables impliquées

Les segments d'annulation et l'espace d'annulation sauraient à quoi ressemblaient les données modifiées avant d'appliquer les modifications. Les fichiers de journalisation sauraient quelles modifications doivent être apportées pour que les données apparaissent mises à jour.

Vous avez également demandé

pourquoi n'est-il pas possible pour une transaction READ_COMMITTED de lire des données non validées, c'est-à-dire d'effectuer une "lecture incorrecte"? Quel mécanisme applique cette restriction?

Les journaux de rétablissement, l'espace d'annulation et les lignes verrouillées entrent en jeu. Vous devez également considérer le pool de tampons InnoDB (où vous pouvez mesurer les pages sales avec innodb_max_dirty_pages_pct , innodb_buffer_pool_pages_dirty et innodb_buffer_pool_bytes_dirty ).

À la lumière de cela, READ COMMITTED saurait à quoi ressemblent les données en permanence. Par conséquent, il n'est pas nécessaire de rechercher des pages sales qui n'ont pas été validées. LIRE ENGAGÉ ne serait rien de plus qu'une sale lecture qui a été commise. READ UNCOMMITTED aurait continué à savoir quelles lignes doivent être verrouillées et quels journaux de rétablissement ont été lus ou ignorés pour rendre les données visibles.

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

RolandoMySQLDBA
la source
1
Tout d'abord, merci pour votre réponse et la modification de mon post ... Donc, avant un COMMIT, les changements ne sont pas visibles pour les autres utilisateurs du système? Ici, l'utilisateur signifie littéralement une transaction, non? Étant donné que READ UNCOMMITTED peut lire des données non validées, où ce niveau d'isolement lit-il ces données? Pourrait-il y avoir plus d'une source de données non validées pour un élément de données particulier dans une base de données? Si oui, quelle donnée non validée sera alors lue?
Shuzheng