Cet article vous apporte une introduction détaillée (images et textes) sur l'isolation des transactions et le MVCC de la base de données MySQL. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Avant-propos : Une transaction est une séquence d'opérations pour accéder à la base de données. Le système d'application de base de données complète l'accès à la base de données via des ensembles de transactions.
1. 🎜>La transaction doit être conforme aux principes ACID établis par l'ISO/IEC. ACID est l'abréviation d'atomicité, de cohérence, d'isolement et de durabilité. La signification de ces quatre états est :
1 Atomicité La caractéristique atomique signifie que toutes les opérations incluses dans une transaction réussissent ou échouent et sont annulées. C'est le même concept que la fonction des transactions introduite dans les deux blogs précédents. Par conséquent, si l'opération de la transaction réussit, elle doit être entièrement appliquée à la base de données. Si l'opération échoue, elle ne peut avoir aucun impact sur la base de données. .
2. Cohérence
La cohérence signifie qu'une transaction doit transformer la base de données d'un état de cohérence à un autre état de cohérence
Isolement
Lorsque la transaction est correcte Avant de s'engager, la transaction modifie les données. ne peuvent être fournis à aucune autre transaction, c'est-à-dire que ses résultats possibles ne doivent pas être affichés à d'autres transactions avant que la transaction ne soit correctement validée
4. Durabilité (Durabilité)
La persistance de la durabilité signifie qu'une fois une transaction. est validée, les modifications apportées aux données dans la base de données sont permanentes et l'opération de validation de la transaction ne sera pas perdue même si le système de base de données rencontre une panne.
2. Le rôle des transactions
Lorsque plusieurs threads démarrent des transactions pour exploiter les données dans la base de données, le système de base de données doit être capable d'effectuer des opérations d'isolation pour garantir l'exactitude des données obtenues par chaque thread. .
3. Problèmes de concurrence rencontrés
1. Le premier type de mise à jour perdue : lorsque la transaction A est révoquée, les données mises à jour de la transaction B qui ont été soumises sont écrasées.
2. .La deuxième mise à jour de perte de classe : la transaction A écrase les données soumises par la transaction B, entraînant la perte du fonctionnement de la transaction B.3. Lecture sale : la transaction A lit les données non validées dans la transaction B.
4. -Lecture répétable : La valeur lue plusieurs fois par la transaction A est différente car la valeur a été modifiée et validée par la transaction B.
5. Lecture fantôme : Entre les deux lectures de la transaction A, la transaction B a inséré des données.
4. Comment résoudre le problème ci-dessus ?
Afin de résoudre le problème ci-dessus, les développeurs ont conçu les quatre niveaux d'isolation des transactions suivants pour la base de données MySQL :
1. : autorisé La lecture sale signifie que les données modifiées par des transactions non validées dans d'autres sessions peuvent être lues
2. Lecture validée : seules les données validées peuvent être lues. La plupart des bases de données telles qu'Oracle utilisent ce niveau par défaut (pas de lectures répétées
3. Les requêtes au sein d'une même transaction sont cohérentes au début de la transaction, niveau par défaut d'InnoDB. Dans la norme SQL, ce niveau d'isolement élimine les lectures non répétables, mais les lectures fantômes existent toujours, mais innoDB résout les lectures fantômes.
Sérialisable (lecture série) : lecture entièrement sérialisée, chaque lecture doit être obtenue. un verrou partagé au niveau de la table, et la lecture et l'écriture se bloqueront mutuellement.
1. Afficher le niveau d'isolement des transactions globales ou de session
SELECT @@global.tx_isolation, @@tx_isolation;
2. level Niveau
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
Ce qui suit présente d'abord les verrous impliqués dans la base de données.
1. Introduction aux verrous
Un verrou dans une base de données fait référence à un mécanisme logiciel utilisé pour contrôler et empêcher un utilisateur (session de processus) d'occuper une certaine ressource de données. d'autres utilisateurs prennent des mesures qui affectent les opérations de données de l'utilisateur ou provoquent des problèmes de non-intégrité et de non-cohérence des données.
2. Niveaux de verrouillage
Selon le niveau de verrouillage, les verrous peuvent être divisés en verrous partagés et verrous exclusifs.
Pour le même bloc de données, plusieurs opérations de lecture peuvent être effectuées en même temps sans s'affecter mutuellement. Les verrous partagés ne sont verrouillés que pendant UPDATE. Avant la soumission de l'opération UPDATE, les autres transactions ne peuvent obtenir que les derniers enregistrements mais ne peuvent pas effectuer d'opérations UPDATE.
Bloquez les autres verrous en écriture et les verrous en lecture avant la fin de l'opération d'écriture en cours.
3. Granularité du verrouillage
Selon la granularité du verrouillage, les verrous peuvent être divisés en verrous au niveau de la table, au niveau de la ligne et au niveau de la page.
Il est coûteux, lent à verrouiller, un blocage se produira, la force de verrouillage est la plus petite, la probabilité de conflit de verrouillage est la plus faible, et la concurrence est élevée.
Faible surcharge, verrouillage rapide, pas de blocage, intensité de verrouillage élevée, forte probabilité de conflit et faible concurrence.
La surcharge et le temps de verrouillage se situent entre le verrouillage de la table et le verrouillage de la ligne, un blocage se produira et l'intensité du verrouillage se situe entre le verrouillage de la table et celui de la ligne. Entre les deux, la concurrence est moyenne.
1 Idée de base : supposez toujours le pire des cas et réfléchissez à chaque fois que vous obtenez les données que d'autres modifieront. il sera donc verrouillé à chaque fois qu'il obtiendra les données. De cette façon, si d'autres personnes souhaitent obtenir les données, elles seront bloquées jusqu'à ce qu'elles obtiennent le verrou (la ressource partagée n'est utilisée que par un thread à la fois, et les autres threads sont bloqués. Après utilisation, les ressources sont transférées vers d'autres threads. De nombreux mécanismes de verrouillage de ce type sont utilisés dans les bases de données relationnelles traditionnelles, tels que les verrous de ligne, les verrous de table, les verrous de lecture, les verrous d'écriture, etc., qui sont tous verrouillés avant les opérations. Par conséquent, peu importe si un conflit se produit réellement, ils seront utilisés comme verrous. mécanisme.
2. Fonction de verrouillage pessimiste :
1. Idée de base : supposez toujours la meilleure situation, et chaque fois que vous allez chercher les données, vous pensez que les autres ne les modifieront pas, alors vous ne le verrouillera pas. , mais lors de la mise à jour, il sera jugé si d'autres ont mis à jour ces données pendant cette période, ce qui peut être implémenté à l'aide du mécanisme de numéro de version et de l'algorithme CAS. Le verrouillage optimiste convient aux types d'applications multi-lectures, ce qui peut améliorer le débit.
2. Explication : Le verrouillage optimiste ne verrouille rien, c'est-à-dire qu'il ne repose pas sur le mécanisme de transaction de la base de données. , Le verrouillage optimiste se situe entièrement au niveau du système d'application. Ce n'est donc pas un mécanisme de verrouillage. Si le verrouillage optimiste est utilisé, la base de données doit ajouter un champ de version, sinon tous les champs ne peuvent être comparés que, mais comme les types à virgule flottante ne peuvent pas être comparés, cela n'est en fait pas réalisable sans un champ de version
Généralement, un champ de numéro de version des données est ajouté au tableau de données pour indiquer le nombre de fois que les données ont été modifiées. Lorsque les données sont modifiées, la valeur de version sera. incrémenté de un. Lorsque le thread A souhaite mettre à jour la valeur des données, il lira également la valeur de version lors de la lecture des données. Lors de la soumission de la mise à jour, mettez-la à jour uniquement si la valeur de version que vous venez de lire est égale à la valeur de version dans la base de données actuelle, sinon réessayez. Opération de mise à jour jusqu’à ce que la mise à jour réussisse.
1. Idée de base : comparer et échanger, c'est-à-dire comparer puis échanger.
2. Processus : supposons que le thread A va modifier la valeur de la variable nommée name dans la mémoire, donc le thread A comparera la valeur de la variable name qu'il a lue auparavant avec la valeur de name à ce moment-là. ils sont identiques, cela signifie que dans La valeur de la variable n'a pas été modifiée, elle peut donc être mise à jour, sinon la mise à jour échoue
Comme mentionné précédemment, MySQL implémente par défaut le niveau d'isolation des transactions de lecture répétable, mais il ne peut pas résoudre le problème des lectures fantômes. Cependant, dans les conditions d'isolation des transactions de la base de données MySQL utilisant des lectures répétables, les lectures fantômes ne l'ont pas fait. se produire. MySQL utilise MVCC (Multi-version Concurrency) Control) a été contrôlé.
1.MVCC:是multiversion concurrency control的简称,也就是多版本并发控制,是个很基本的概念。MVCC的作用是让事务在并行发生时,在一定隔离级别前提下,可以保证在某个事务中能实现一致性读,也就是该事务启动时根据某个条件读取到的数据,直到事务结束时,再次执行相同条件,还是读到同一份数据,不会发生变化(不会看到被其他并行事务修改的数据)。
2.read view:InnoDB MVCC使用的内部快照的意思。在不同的隔离级别下,事务启动时(有些情况下,可能是SQL语句开始时)看到的数据快照版本可能也不同。在上面介绍的几个隔离级别下会用到 read view。
3.快照读: 就是所谓的根据read view去获取信息和数据,不会加任何的锁。
4.当前读:前读会获取得到所有已经提交数据,按照逻辑上来讲的话,在一个事务中第一次当前读和第二次当前读的中间有新的事务进行DML操作,这个时候俩次当前读的结果应该是不一致的,但是实际的情况却是在当前读的这个事务还没提交之前,所有针对当前读的数据修改和插入都会被阻塞,主要是因为next-key lock解决了当前读可能会发生幻读的情况。
next-key lock当使用主键索引进行当前读的时候,会降级为record lock(行锁)
InnoDB支持MVCC多版本控制,其中READ COMMITTED和REPEATABLE READ隔离级别是利用consistent read view(一致读视图)方式支持的。所谓的consistent read view就是在某一时刻给事务系统trx_sys打snapshot(快照),把当时的trx_sys状态(包括活跃读写事务数组)记下来,之后的所有读操作根据其事务ID(即trx_id)与snapshot中trx_sys的状态做比较,以此判断read view对事务的可见性。
REPEATABLE READ隔离级别(除了GAP锁之外)和READ COMMITTED隔离级别的差别是创建snapshot时机不同。REPEATABLE READ隔离级别是在事务开始时刻,确切的说是第一个读操作创建read view的时候,READ COMMITTED隔离级别是在语句开始时刻创建read view的。这就意味着REPEATABLE READ隔离级别下面一个事务的SELECT操作只会获取一个read view,但是READ COMMITTED隔离级别下一个事务是可以获取多个read view的。
创建/关闭read view需要持有trx_sys->mutex,会降低系统性能,5.7版本对此进行优化,在事务提交时session会cache只读事务的read view。
在InnoDB中,创建一个新事务的时候,InnoDB会将当前系统中的活跃事务列表(trx_sys->trx_list)创建一个副本(read view),副本中保存的是系统当前不应该被本事务看到的其他事务id列表。当用户在这个事务中要读取该行记录的时候,InnoDB会将该行当前的版本号与该read view进行比较。
具体的算法如下:
设该行的当前事务id为trx_id,read view中最早的事务id为trx_id_min, 最迟的事务id为trx_id_max。
如果trx_id如果trx_id>trx_id_max的话,那么表明该行记录所在的事务在本次新事务创建之后才开启,所以该行记录的当前值不可见。
如果trx_id_min
从该行记录的DB_ROLL_PTR指针所指向的回滚段中取出最新的undo-log的版本号的数据,将该可见行的值返回。
需要注意的是,新建事务(当前事务)与正在内存中commit 的事务不在活跃事务链表中。
在具体多版本控制中我们先来看下源码:
函数:read_view_sees_trx_id。 read_view中保存了当前全局的事务的范围: 【low_limit_id, up_limit_id】 1.当行记录的事务ID小于当前系统的最小活动id,就是可见的。 if (trx_id up_limit_id) { return(TRUE); } 2.当行记录的事务ID大于当前系统的最大活动id(也就是尚未分配的下一个事务的id),就是不可见的。 if (trx_id >= view->low_limit_id) { return(FALSE); } 3.当行记录的事务ID在活动范围之中时,判断是否在活动链表中,如果在就不可见,如果不在就是可见的。 for (i = 0; i <p><strong>Read view 图解</strong>:<br></p><p><img src="https://img.php.cn/upload/image/428/162/665/1553653110536794.jpg" title="1553653110536794.jpg" alt="Introduction détaillée à lisolation des transactions et au MVCC de la base de données MySQL (image et texte)"></p><p style="max-width:90%">结语:笔者水平有限,文中如有不妥,请大家多多指教,MySQL数据库事务机制还有很多需要深入研究的,我们仍需不断钻研。</p><p>本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的<a href="http://www.php.cn/course/list/51.html" target="_blank">MySQL视频教程</a>栏目!</p><p></p>
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!