Maison > Article > base de données > Qu'est-ce qu'une transaction dans MySQL
Dans MySQL, une transaction est un mécanisme, une séquence d'opérations et une unité d'exécution de programme permettant d'accéder et de mettre à jour la base de données. Une transaction contient une ou plusieurs commandes d'opération de base de données, et toutes les commandes seront soumises ou révoquées au système dans son ensemble, c'est-à-dire que ce groupe de commandes de base de données sera exécuté ou qu'aucune d'entre elles ne sera exécutée.
L'environnement d'exploitation de ce tutoriel : système windows7, version mysql5.6, ordinateur Dell G3.
Une transaction de base de données est un mécanisme, une séquence d'opérations et une unité d'exécution de programme pour accéder et mettre à jour la base de données. Elle comprend un ensemble de commandes d'opération de base de données.
Une transaction soumet ou révoque une demande d'opération au système avec toutes les commandes dans leur ensemble, c'est-à-dire que cet ensemble de commandes de base de données est soit toutes exécutées, soit aucune n'est exécutée, la transaction est donc une unité de travail logique indivisible.
Lors de l'exécution d'opérations simultanées sur un système de base de données, les transactions sont utilisées comme la plus petite unité de contrôle, ce qui est particulièrement adapté aux systèmes de bases de données exploités par plusieurs utilisateurs en même temps.
En tant que base de données relationnelle, MySQL prend en charge les transactions. Cet article est basé sur MySQL5.6.
Revoyez d’abord les bases des transactions MySQL.
1. Architecture logique et moteur de stockage
Source de l'image : https://blog.csdn.net/fuzhongmin05/article/details/70904190
Comme le montre la figure ci-dessus, le serveur MySQL l'architecture logique commence par Elle peut être divisée en trois couches de haut en bas :
(1) La première couche : gère les connexions clients, l'authentification des autorisations, etc.
(2) Deuxième couche : couche serveur, responsable de l'analyse, de l'optimisation, de la mise en cache des instructions de requête, de la mise en œuvre des fonctions intégrées, des procédures stockées, etc.
(3) La troisième couche : moteur de stockage, responsable du stockage et de la récupération des données dans MySQL. La couche serveur dans MySQL ne gère pas les transactions et les transactions sont implémentées par le moteur de stockage. Les moteurs de stockage MySQL qui prennent en charge les transactions incluent InnoDB, NDB Cluster, etc., parmi lesquels InnoDB est le plus largement utilisé ; les autres moteurs de stockage ne prennent pas en charge les transactions, telles que MyIsam, Memory, etc.
Sauf indication contraire, le contenu décrit dans l'article suivant est basé sur InnoDB.
2. Soumettre et annuler
Une transaction MySQL typique fonctionne comme suit :
start transaction; …… #一条或多条sql语句 commit;
où start transaction identifie le début de la transaction, commit valide la transaction et écrit les résultats de l'exécution dans la base de données. S'il y a un problème avec l'exécution des instructions SQL, rollback sera appelé pour annuler toutes les instructions SQL qui ont été exécutées avec succès. Bien entendu, vous pouvez également utiliser l'instruction rollback directement dans la transaction pour annuler.
Autocommit
MySQL utilise le mode autocommit par défaut, comme indiqué ci-dessous :
En mode autocommit, s'il n'y a pas de start transaction pour démarrer explicitement une transaction, alors chaque instruction SQL sera traitée comme une transaction à effectuer une opération de validation.
Vous pouvez désactiver la validation automatique des manières suivantes : il convient de noter que les paramètres de validation automatique sont spécifiques à la connexion. La modification des paramètres dans une connexion n'affectera pas les autres connexions.
Si la validation automatique est désactivée, toutes les instructions SQL sont dans une seule transaction jusqu'à ce que la validation ou l'annulation soit exécutée, la transaction se termine et une autre transaction démarre.
Opérations spéciales
Dans MySQL, il existe des commandes spéciales si ces commandes sont exécutées dans une transaction, la validation sera forcée d'exécuter la transaction immédiatement, comme les instructions DDL (create table/drop table/alter/table) ), instruction de verrouillage des tables, etc.
Cependant, les commandes de sélection, d'insertion, de mise à jour et de suppression couramment utilisées ne forceront pas la validation de la transaction.
3. Caractéristiques ACIDE
L'ACIDE est les quatre caractéristiques qui mesurent les transactions :
Selon des normes strictes normes, seules les transactions qui répondent en même temps aux caractéristiques ACID sont considérées comme des transactions ; cependant, dans les implémentations des principaux fournisseurs de bases de données, il existe très peu de transactions qui répondent réellement à ACID. Par exemple, la transaction du cluster NDB de MySQL ne répond pas à la durabilité et à l'isolation ; le niveau d'isolation des transactions par défaut d'InnoDB est une lecture répétable, ce qui ne satisfait pas à l'isolation ; le niveau d'isolation des transactions par défaut d'Oracle est READ COMMITTED, qui ne satisfait pas à l'isolation... Donc, au lieu de disant ACID sont les conditions que les transactions doivent remplir. Ce sont plutôt les quatre dimensions de la mesure des transactions.
Les caractéristiques ACID et leurs principes de mise en œuvre seront présentés en détail ci-dessous pour faciliter la compréhension, l'ordre d'introduction n'est pas strictement A-C-I-D.
1. Définition
L'atomicité signifie qu'une transaction est une unité de travail indivisible, dans laquelle les opérations sont effectuées ou aucune ; si une instruction SQL dans la transaction ne s'exécute pas, l'instruction exécutée doit également être annulée et la base de données revient à la transaction précédente. statut.
2. Principe de mise en œuvre : annuler le journal
Avant d'expliquer le principe de l'atomicité, introduisez d'abord le journal des transactions MySQL. Il existe de nombreux types de journaux MySQL, tels que les journaux binaires, les journaux d'erreurs, les journaux de requêtes, les journaux de requêtes lentes, etc. De plus, le moteur de stockage InnoDB fournit également deux types de journaux de transactions : redo log (redo log) et undo log ( journal de restauration). Le journal redo est utilisé pour garantir la durabilité des transactions ; le journal d'annulation est la base de l'atomicité et de l'isolation des transactions.
Parlons du journal d'annulation. La clé pour parvenir à l'atomicité est de pouvoir annuler toutes les instructions SQL exécutées avec succès lorsque la transaction est annulée. InnoDB réalise la restauration en s'appuyant sur le journal d'annulation : lorsqu'une transaction modifie la base de données, InnoDB générera le journal d'annulation correspondant si l'exécution de la transaction échoue ou si le rollback est appelé, la transaction devra Pour restaurer, vous pouvez utiliser les informations du journal d'annulation pour restaurer les données telles qu'elles étaient avant la modification.
undo log est un journal logique qui enregistre les informations liées à l'exécution de SQL. Lorsqu'un rollback se produit, InnoDB fera le contraire du travail précédent en fonction du contenu du journal d'annulation : pour chaque insertion, une suppression sera exécutée lors du rollback ; pour chaque suppression, une insertion sera exécutée lors du rollback pour chaque mise à jour ; , une suppression sera exécutée lors de la restauration. Lors du rollback, une mise à jour inverse sera effectuée pour modifier les données.
Prenons l'exemple de l'opération de mise à jour : lorsqu'une transaction exécute une mise à jour, le journal d'annulation généré contiendra des informations telles que la clé primaire de la ligne modifiée (afin de savoir quelles lignes ont été modifiées), quelles colonnes ont été modifiées , et les valeurs de ces colonnes avant et après modification , vous pouvez utiliser ces informations pour restaurer les données à l'état avant la mise à jour lors de la restauration.
1. Définition
La persistance signifie qu'une fois qu'une transaction est validée, ses modifications dans la base de données doivent être permanentes. Les opérations ou pannes ultérieures ne devraient avoir aucun impact sur celui-ci.
2. Principe de mise en œuvre : redo log
Le redo log et l'annulation du journal appartiennent au journal des transactions InnoDB. Parlons d’abord du contexte de l’existence du redo log.
InnoDB est le moteur de stockage de MySQL et les données sont stockées sur le disque. Cependant, si des E/S disque sont nécessaires à chaque fois pour lire et écrire des données, l'efficacité sera très faible. A cet effet, InnoDB fournit un cache (Buffer Pool). Le Buffer Pool contient le mappage de certaines pages de données sur le disque et sert de tampon pour accéder à la base de données : lors de la lecture des données de la base de données, elles seront d'abord lues depuis le Pool de tampons. Si le pool de tampons n'existe pas dans le pool, il sera lu à partir du disque et placé dans le pool de tampons ; lors de l'écriture des données dans la base de données, il sera d'abord écrit dans le pool de tampons, puis modifié. les données du pool de tampons seront régulièrement actualisées sur le disque (ce processus est appelé « dirty flushing »).
L'utilisation de Buffer Pool améliore considérablement l'efficacité de la lecture et de l'écriture des données, mais elle entraîne également de nouveaux problèmes : si MySQL tombe en panne et que les données modifiées dans le Buffer Pool n'ont pas été vidées sur le disque, cela entraînera une perte de données. La durabilité des transactions n’est pas garantie.
Ainsi, le redo log a été introduit pour résoudre ce problème : lorsque les données sont modifiées, en plus de modifier les données dans le Buffer Pool, l'opération sera également enregistrée dans le redo log lorsque la transaction est soumise, l'interface fsync ; sera appelé pour vider la plaque de refaire. Si MySQL tombe en panne, vous pouvez lire les données dans le journal redo et restaurer la base de données au redémarrage. Le journal redo utilise WAL (Write-ahead logging, write-ahead log). Toutes les modifications sont d'abord écrites dans le journal puis mises à jour dans le pool de tampons, garantissant que les données ne seront pas perdues en raison du temps d'arrêt de MySQL, respectant ainsi la durabilité. exigences.
Puisque le journal redo doit également écrire le journal sur le disque lorsque la transaction est validée, pourquoi est-ce plus rapide que d'écrire directement les données modifiées dans le pool de tampons sur le disque (c'est-à-dire de les salir) ? Il y a principalement deux raisons :
(1) Le nettoyage sale est une IO aléatoire, car l'emplacement des données modifié à chaque fois est aléatoire, mais l'écriture du journal redo est une opération d'ajout et appartient aux IO séquentielles.
(2) L'unité de salissage est la page de données (Page). La taille de page par défaut de MySQL est de 16 Ko. Une petite modification sur une page nécessite l'écriture de la page entière tandis que le redo log ne contient que la partie qui en a réellement besoin. à écrire, les E/S invalides sont considérablement réduites.
3. redo log et binlog
Nous savons qu'il existe également un binlog (journal binaire) dans MySQL qui peut également enregistrer des opérations d'écriture et être utilisé pour la récupération de données, mais les deux sont fondamentalement différents :
(1) Différentes fonctions : le journal redo est utilisé pour la récupération après incident afin de garantir que les temps d'arrêt de MySQL n'affecteront pas la durabilité ; le journal binaire est utilisé pour la récupération à un moment précis afin de garantir que le serveur peut récupérer les données en fonction des points temporels. également utilisé pour la réplication maître-esclave.
(2) Différents niveaux : le redo log est implémenté par le moteur de stockage InnoDB, tandis que binlog est implémenté par la couche serveur MySQL (veuillez vous référer à l'introduction de l'architecture logique MySQL plus haut dans l'article), et prend en charge à la fois InnoDB et d'autres moteurs de stockage.
(3)内容不同:redo log是物理日志,内容基于磁盘的Page;binlog的内容是二进制的,根据binlog_format参数的不同,可能基于sql语句、基于数据本身或者二者的混合。
(4)写入时机不同:binlog在事务提交时写入;redo log的写入时机相对多元:
1. 定义
与原子性、持久性侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响。隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。
隔离性追求的是并发情形下事务之间互不干扰。简单起见,我们主要考虑最简单的读操作和写操作(加锁读等特殊读操作会特殊说明),那么隔离性的探讨,主要可以分为两个方面:
2. 锁机制
首先来看两个事务的写操作之间的相互影响。隔离性要求同一时刻只能有一个事务对数据进行写操作,InnoDB通过锁机制来保证这一点。
锁机制的基本原理可以概括为:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。
行锁与表锁
按照粒度,锁可以分为表锁、行锁以及其他位于二者之间的锁。表锁在操作数据时会锁定整张表,并发性能较差;行锁则只锁定需要操作的数据,并发性能好。但是由于加锁本身需要消耗资源(获得锁、检查锁、释放锁等都需要消耗资源),因此在锁定数据较多情况下使用表锁可以节省大量资源。MySQL中不同的存储引擎支持的锁是不一样的,例如MyIsam只支持表锁,而InnoDB同时支持表锁和行锁,且出于性能考虑,绝大多数情况下使用的都是行锁。
如何查看锁信息
有多种方法可以查看InnoDB中锁的情况,例如:
select * from information_schema.innodb_locks; #锁的概况 show engine innodb status; #InnoDB整体状态,其中包括锁的情况
下面来看一个例子:
#在事务A中执行: start transaction; update account SET balance = 1000 where id = 1; #在事务B中执行: start transaction; update account SET balance = 2000 where id = 1;
此时查看锁的情况:
show engine innodb status查看锁相关的部分:
通过上述命令可以查看事务24052和24053占用锁的情况;其中lock_type为RECORD,代表锁为行锁(记录锁);lock_mode为X,代表排它锁(写锁)。
除了排它锁(写锁)之外,MySQL中还有共享锁(读锁)的概念。由于本文重点是MySQL事务的实现原理,因此对锁的介绍到此为止,后续会专门写文章分析MySQL中不同锁的区别、使用场景等,欢迎关注。
介绍完写操作之间的相互影响,下面讨论写操作对读操作的影响。
3. 脏读、不可重复读和幻读
首先来看并发情况下,读操作可能存在的三类问题:
(1)脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据),这种现象是脏读。举例如下(以账户余额表为例):
(2)不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。举例如下:
(3) Lecture fantôme : Dans la transaction A, la base de données est interrogée deux fois selon une certaine condition, et le nombre de résultats des deux requêtes est différent. Ce phénomène est appelé lecture fantôme. La différence entre la lecture non répétable et la lecture fantôme peut être facilement comprise comme suit : la première signifie que les données ont changé, et la seconde signifie que le nombre de lignes de données a changé. Par exemple :
4. Niveau d'isolement des transactions
La norme SQL définit quatre niveaux d'isolement et stipule si les problèmes ci-dessus existent sous chaque niveau d'isolement. De manière générale, plus le niveau d'isolement est faible, plus la surcharge du système est faible, plus la simultanéité pouvant être prise en charge est élevée, mais plus l'isolement est mauvais. La relation entre les niveaux d'isolement et les problèmes de lecture est la suivante :
Dans les applications réelles, lecture non validée causera de nombreux problèmes lors de la simultanéité, mais l'amélioration des performances est très limitée par rapport aux autres niveaux d'isolement, il est donc moins utilisé . SérialisableEn forçant la sérialisation des transactions, l'efficacité de la concurrence est très faible. Elle ne peut être utilisée que lorsque les exigences de cohérence des données sont extrêmement élevées et qu'aucune concurrence n'est acceptable, elle est donc rarement utilisée. Par conséquent, dans la plupart des systèmes de bases de données, le niveau d'isolement par défaut est Lecture validée (comme Oracle) ou Lecture répétable (ci-après dénommée RR).
Vous pouvez afficher le niveau d'isolement global et le niveau d'isolement de cette session via les deux commandes suivantes :
Le niveau d'isolement par défaut d'InnoDB est RR, et nous nous concentrerons sur RR plus tard. Il convient de noter que dans le standard SQL, RR ne peut pas éviter le problème de lecture fantôme, mais le RR implémenté par InnoDB évite le problème de lecture fantôme.
5. MVCC
RR résout des problèmes tels que les lectures sales, les lectures non répétables, les lectures fantômes, etc. Il utilise MVCC : le nom complet de MVCC est Multi-Version Concurrency Control, qui est une concurrence multi-versions. protocole de contrôle. L'exemple suivant reflète bien les caractéristiques de MVCC : en même temps, les données lues par différentes transactions peuvent être différentes (c'est-à-dire plusieurs versions) - au moment T5, la transaction A et la transaction C peuvent lire des données de versions différentes.
Le plus grand avantage de MVCC est que la lecture n'est pas verrouillée, il n'y a donc pas de conflit entre la lecture et l'écriture, et les performances de concurrence sont bonnes. InnoDB implémente MVCC, et plusieurs versions de données peuvent coexister, principalement basées sur les technologies et structures de données suivantes :
1) Colonnes cachées : chaque ligne de données dans InnoDB a des colonnes cachées, et les colonnes cachées contiennent l'identifiant de transaction et le pointeur de cette ligne de données. Annuler le pointeur de journal, etc.
2) Chaîne de versions basée sur le journal d'annulation : comme mentionné précédemment, la colonne cachée de chaque ligne de données contient un pointeur vers le journal d'annulation, et chaque journal d'annulation pointera également vers une version antérieure du journal d'annulation, formant ainsi un chaîne de versions.
3) ReadView : en masquant les colonnes et les chaînes de versions, MySQL peut restaurer les données vers une version spécifiée, mais la version à restaurer doit être déterminée en fonction de ReadView ; Ce qu'on appelle ReadView signifie qu'une transaction (enregistrée comme transaction A) prend un instantané de l'ensemble du système de transaction (trx_sys) à un certain moment. Lorsqu'une opération de lecture est effectuée ultérieurement, l'ID de transaction dans les données lues sera comparé à. l'instantané trx_sys, donc Déterminez si les données sont visibles par ReadView, c'est-à-dire si elles sont visibles par la transaction A.
Le contenu principal de trx_sys et la méthode de jugement de la visibilité sont les suivants :
Ce qui suit prend le niveau d'isolement RR comme exemple et l'explique séparément en fonction des plusieurs problèmes mentionnés ci-dessus.
(1) Lecture sale
当事务A在T3时刻读取zhangsan的余额前,会生成ReadView,由于此时事务B没有提交仍然活跃,因此其事务id一定在ReadView的rw_trx_ids中,因此根据前面介绍的规则,事务B的修改对ReadView不可见。接下来,事务A根据指针指向的undo log查询上一版本的数据,得到zhangsan的余额为100。这样事务A就避免了脏读。
(2)不可重复读
当事务A在T2时刻读取zhangsan的余额前,会生成ReadView。此时事务B分两种情况讨论,一种是如图中所示,事务已经开始但没有提交,此时其事务id在ReadView的rw_trx_ids中;一种是事务B还没有开始,此时其事务id大于等于ReadView的low_limit_id。无论是哪种情况,根据前面介绍的规则,事务B的修改对ReadView都不可见。
当事务A在T5时刻再次读取zhangsan的余额时,会根据T2时刻生成的ReadView对数据的可见性进行判断,从而判断出事务B的修改不可见;因此事务A根据指针指向的undo log查询上一版本的数据,得到zhangsan的余额为100,从而避免了不可重复读。
(3)幻读
MVCC避免幻读的机制与避免不可重复读非常类似。
当事务A在T2时刻读取0 当事务A在T5时刻再次读取0 扩展 前面介绍的MVCC,是RR隔离级别下“非加锁读”实现隔离性的方式。下面是一些简单的扩展。 (1)读已提交(RC)隔离级别下的非加锁读 RC与RR一样,都使用了MVCC,其主要区别在于: RR是在事务开始后第一次执行select前创建ReadView,直到事务提交都不会再创建。根据前面的介绍,RR可以避免脏读、不可重复读和幻读。 RC每次执行select前都会重新建立一个新的ReadView,因此如果事务A第一次select之后,事务B对数据进行了修改并提交,那么事务A第二次select时会重新建立新的ReadView,因此事务B的修改对事务A是可见的。因此RC隔离级别可以避免脏读,但是无法避免不可重复读和幻读。 (2)加锁读与next-key lock 按照是否加锁,MySQL的读可以分为两种: 一种是非加锁读,也称作快照读、一致性读,使用普通的select语句,这种情况下使用MVCC避免了脏读、不可重复读、幻读,保证了隔离性。 另一种是加锁读,查询语句有所不同,如下所示: 加锁读在查询时会对查询的数据加锁(共享锁或排它锁)。由于锁的特性,当某事务对数据进行加锁读后,其他事务无法对数据进行写操作,因此可以避免脏读和不可重复读。而避免幻读,则需要通过next-key lock。next-key lock是行锁的一种,实现相当于record lock(记录锁) + gap lock(间隙锁);其特点是不仅会锁住记录本身(record lock的功能),还会锁定一个范围(gap lock的功能)。因此,加锁读同样可以避免脏读、不可重复读和幻读,保证隔离性。 6. 总结 En résumé, le RR implémenté par InnoDB atteint un certain degré d'isolation grâce au mécanisme de verrouillage (y compris le verrouillage à la touche suivante), MVCC (y compris les colonnes de données cachées, la chaîne de versions basée sur le journal d'annulation, ReadView), etc., qui peuvent satisfaire Requis dans la plupart des scénarios. Cependant, il convient de noter que bien que RR évite le problème de lecture fantôme, il n'est finalement pas sérialisable et ne peut pas garantir une isolation complète : Le premier exemple, si la première lecture de la transaction est non-. lecture verrouillée, la deuxième lecture utilise la lecture verrouillée, si les données changent entre les deux lectures, les résultats des deux lectures sont différents, car MVCC n'est pas utilisé lors des lectures verrouillées. Le deuxième exemple est celui indiqué ci-dessous, vous pouvez le vérifier vous-même. 1. Concept de base La cohérence signifie qu'après l'exécution de la transaction, les contraintes d'intégrité de la base de données ne sont pas détruites et l'état des données est légal avant et après l'exécution de la transaction. . Les contraintes d'intégrité de la base de données incluent, sans s'y limiter : l'intégrité de l'entité (telle que la clé primaire de la ligne existe et est unique), l'intégrité des colonnes (telle que le type, la taille et la longueur du champ doivent répondre aux exigences) , les contraintes de clé étrangère et l'intégrité définie par l'utilisateur (par exemple, avant et après le transfert, la somme des soldes des deux comptes doit rester inchangée). 2. Implémentation 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!#共享锁读取
select...lock in share mode
#排它锁读取
select...for update
Cohérence
Garantir l'atomicité, la durabilité et l'isolement. Si ces caractéristiques ne peuvent pas être garanties, la cohérence de la transaction ne peut pas être garantie
RésuméCe qui suit résume les caractéristiques d'ACID et leurs principes de mise en œuvre :
Atomicité : les instructions sont soit entièrement exécutées, soit pas exécutées du tout, ce qui est le cas. caractéristique principale d'une transaction.La transaction elle-même est définie par l'atomicité;La mise en œuvre est principalement basée sur l'annulation du journal