Maison > Article > base de données > Quel est le mécanisme MVCC dans MySQL
MVCC, le nom complet est Multi-Version Concurrency Control, qui est un contrôle de concurrence multi-version. MVCC est une méthode de contrôle multi-accès simultanés. Elle est généralement utilisée dans les systèmes de gestion de bases de données pour obtenir un accès simultané à la base de données et pour implémenter une mémoire transactionnelle dans les langages de programmation.
Nous savons que MySql est passé du moteur de stockage MyISAM au moteur de stockage InnoDB après la version 5.5, principalement parce qu'InnoDB prend en charge les transactions, donc lorsque plusieurs threads sont exécutés en même temps, des problèmes de concurrence peuvent survenir. À ce stade, une méthode permettant de contrôler la concurrence peut apparaître, et MVCC joue ce rôle.
MVCC est principalement implémenté par la chaîne de versions d'annulation du journal et ReadView.
Le journal d'annulation est principalement utilisé pour restaurer les données d'origine lorsqu'une transaction est annulée.
Lorsque MySQL exécute SQL, il enregistre le journal du jour logiquement opposé au journal d'annulation. Par conséquent, ce qui est enregistré dans le journal d’annulation est également un journal logique.
Mais lorsque mysql exécute l'instruction Insert, l'identifiant de clé primaire de cette insertion sera enregistré dans le journal d'annulation. Lorsque la transaction est annulée, delete supprime cet identifiant.
Lors de l'exécution de l'instruction de mise à jour, MySQL enregistrera les données avant modification dans le journal d'annulation. Lorsque la transaction est annulée, la mise à jour est à nouveau effectuée pour obtenir les données d'origine.
Lorsque MySQL exécute l'instruction de suppression, les données avant la suppression seront enregistrées dans le journal d'annulation. Lorsque la transaction est annulée, exécutez à nouveau insert et insérez les données d'origine.
Les quatre caractéristiques principales de la base de données - l'atomicité, c'est-à-dire que les transactions sont indivisibles, soit toutes réussissent, soit toutes échouent, et la couche inférieure est obtenue par annulation du journal. Lorsque l'exécution d'une certaine instruction échoue, les instructions de la transaction précédente seront annulées.
Sur chaque ligne de la base de données, en plus de stocker les données réelles, il y a également 3 colonnes cachées : row_id, trx_id et roll_pointer
row_id, numéro de ligne :
Si la table actuelle a une clé primaire de type entier, alors la valeur de row_id est la valeur de la clé primaire
S'il n'y a pas de clé primaire de type entier, MySQL sélectionnera un index unique de type entier non vide comme row_id dans l'ordre des champs
Si aucun des deux n'est trouvé, un entier croissant automatiquement sera créé sous la forme row_id
trx_id, numéro de transaction :
Lorsqu'une transaction commence à être exécutée, MySQL allouera un transaction d'incrémentation automatique vers l'identifiant de la transaction.
Ensuite, lorsque la transaction effectue des opérations telles que l'ajout, la modification ou la suppression des données actuelles, elle enregistrera son propre ID de transaction dans trx_id.
roll_pointer, pointeur de restauration :
Lorsqu'une transaction modifie les données actuelles, les anciennes données seront enregistrées dans le journal d'annulation, et les données seront écrites dans la ligne actuelle, et les points roll_pointer actuels au journal d'annulation qui vient d'être enregistré, la version précédente peut donc être trouvée via roll_pointer.
Lorsque des transactions modifient la ligne, un journal d'annulation sera généré en continu et une chaîne de versions de journal d'annulation sera finalement formée.
Au début, nous utilisons l'instruction suivante pour créer une table standard
CREATE TABLE `student` ( `id` INT ( 11 ) NOT NULL AUTO_INCREMENT, `name` VARCHAR ( 255 ) NOT NULL, `age` INT ( 11 ) NOT NULL, PRIMARY KEY ( `id` ) USING BTREE ) ENGINE = INNODB;
Ouvrez maintenant la première transaction, l'identifiant de la transaction est 1 et exécutez l'instruction d'insertion suivante.
INSERT INTO student VALUES ( 1, "a", 24 );
Ensuite, le diagramme actuel est le suivant :
Parce que les données sont nouvellement insérées, le journal d'annulation pointé par son roll_pointer est vide.
Ensuite, ouvrez la deuxième transaction, l'ID de transaction attribué est 2 et exécutez la commande de modification suivante.
UPDATE student SET NAME = 'b' WHERE id = 1;
Le diagramme actuel devient :
Lorsque la troisième transaction est ouverte et que l'identifiant de transaction attribué est 3, exécutez la commande de modification suivante.
UPDATE student SET age = 25 WHERE id = 1;
Le diagramme devient :
Lorsque chaque transaction modifie la ligne, un journal d'annulation sera généré pour enregistrer la version précédente, puis pointera la nouvelle version de roll_pointer vers le journal d'annulation qui vient d'être généré.
Par conséquent, roll_pointer peut connecter ces différentes versions de journaux d'annulation en série pour former une chaîne de versions de journaux d'annulation.
Tout d'abord, vous devez comprendre la lecture d'instantanés et la lecture actuelle
Lecture d'instantanés : une requête de sélection simple, qui n'inclut pas le verrouillage de sélection … en mode partage, sélectionne … historique de la version des données.
Lecture actuelle : les déclarations suivantes sont toutes des lectures actuelles, lisez toujours la dernière version et verrouillez la dernière version lue.
select ... lock in share mode select ... for update insert update delete
Lorsqu'une transaction effectue chaque lecture d'instantané ou lorsqu'une transaction effectue une lecture d'instantané pour la première fois, une vue cohérente, à savoir ReadView, sera générée.
La fonction de ReadView est de déterminer quelles données de la chaîne de versions du journal d'annulation sont visibles pour la transaction en cours.
m_ids
Au moment où ReadView est créé, la collection de tous les ID de transaction non validés dans MySQL.
min_trx_id
m_ids中的最小值
max_trx_id
mysql即将为下一个事务分配的事务id,并不是m_ids中的最大值。
creator_trx_id
即创建此ReadView的事务id
简要的示意图如下:
那么事务在执行快照读时,可以通过以下的规则来确定undo log版本链上的哪个版本数据可见。
如果当前undo log的版本的trx_id
如果当前undo log的版本的trx_id≥max_trx_id,说明该版本对应的事务在生成ReadView之后才开始的,因此是不可见的。
如果当前undo log的版本的trx_id∈[min_trx_id,max_trx_id),如果在这个范围里,还要判断trx_id是否在m_ids中:
在m_ids中,说明版本对应的事务未提交,因此是不可见的。 不在m_ids中,说明版本对应的事务已经提交,因此是可见的。
如果当前undo log的版本的trx_id=creator_trxt_id,说明事务正在访问自己修改的数据,因此是可见的。
当undo log版本链表的头结点数据被判定为不可见时,则利用roll_pointer找到上一个版本,再进行判断。如果整个链表中都没有找到可见的数据,则代表当前的查询找不到数据。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!