Maison > Article > base de données > Une brève analyse du niveau d'isolation des transactions dans MySQL et une discussion de ses principes de mise en œuvre
Cet article vous amènera à comprendre les transactions dans MySQL et à parler du principe de mise en œuvre de l'isolation des transactions. J'espère qu'il pourra vous aider !
En parlant de transactions de base de données, un tas de connaissances liées aux transactions doivent facilement apparaître dans l'esprit de chacun, comme les caractéristiques ACID des transactions, les niveaux d'isolement, les problèmes résolus (lectures sales, lectures non répétables, lectures fantômes) , etc. , mais peu de gens savent vraiment comment ces caractéristiques des transactions sont mises en œuvre et pourquoi il existe quatre niveaux d'isolement.
Aujourd'hui, nous parlerons d'abord du principe de mise en œuvre de l'isolation des transactions dans MySQL, et nous continuerons à publier des articles pour analyser les principes de mise en œuvre d'autres fonctionnalités à l'avenir.
Bien sûr, MySQL est complet et profond, et les omissions dans l'article sont inévitables. Les critiques et les corrections sont les bienvenues.
Explication
La logique d'implémentation des transactions de MySQL est située au niveau de la couche moteur, et tous les moteurs ne prennent pas en charge les transactions. Les instructions suivantes sont basées sur le moteur InnoDB.
L'isolement fait référence au fait qu'après que différentes transactions soient soumises et exécutées les unes après les autres, l'effet final est en série, c'est-à-dire que pour une transaction, les données qu'elle perçoit lors de son exécution ne doivent être provoquées que par. vos propres opérations, et il ne devrait y avoir aucune modification de données causée par d'autres transactions.
L'isolement résout le problème des transactions simultanées.
Le moyen le plus simple de mettre en œuvre l'isolation est que chaque transaction est exécutée en série. Si la transaction précédente n'est pas terminée, les transactions suivantes attendront. Cependant, cette méthode d’implémentation n’est évidemment pas très efficace en simultanéité et n’est pas adaptée à une utilisation dans des environnements réels.
Afin de résoudre les problèmes ci-dessus et d'atteindre différents niveaux de contrôle de concurrence, les créateurs de standards SQL ont proposé différents niveaux d'isolement : lecture non validée (lecture non validée), lecture validée (lecture validée), lecture répétable (lecture répétable), séquence sérialisable. Le niveau d'isolement le plus avancé est la lecture sérialisée, et dans d'autres niveaux d'isolement, puisque les transactions sont exécutées simultanément, certains problèmes sont plus ou moins autorisés. Voir le tableau matriciel suivant :
Niveau d'isolement (+ : autorisé à se produire, - : non autorisé) | lecture sale | lecture non répétable | lecture fantôme | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Ne pas soumettre la lecture | + | + | + | |||||||||||||||||
Soumettre la lecture | - | |||||||||||||||||||
+ | peut être lu à plusieurs reprises | - | ||||||||||||||||||
+ | séquence Lecture chimique Notez que le moteur InnoDB de MySQL résout le problème de lecture fantôme grâce à des verrous d'espacement au niveau de lecture répétable, et résout le problème de lecture non répétable via MVCC. Voir l'analyse ci-dessous pour plus de détails. Principe d'implémentationPrincipe d'implémentation du niveau d'isolement des transactions SQL standardLe problème que nous avons rencontré ci-dessus est en fait le problème de contrôle sous les transactions simultanées. Le moyen le plus courant de résoudre les transactions simultanées est le contrôle de concurrence pessimiste (c'est-à-dire les verrous dans la base de données). . La mise en œuvre du niveau d'isolation des transactions SQL standard repose sur des verrous. Paire de transactions Les données en cours de lecture sont non verrouillé ;
可以看到,InnoDB通过MVCC很好的解决了读写冲突的问题,而且提前一个级别就解决了标准级别下会出现的幻读问题,大大提升了数据库的并发能力。 一些常见误区幻读到底包不包括了delete的情况?不可重复读:前后多次读取一行,数据内容不一致,针对其他事务的update和delete操作。为了解决这个问题,使用行共享锁,锁定到事务结束(也就是RR级别,当然MySQL使用MVCC在RC级别就解决了这个问题) 幻读:当同一个查询在不同时间生成不同的行集合时就是出现了幻读,针对的是其他事务的insert操作,为了解决这个问题,锁定整个表到事务结束(也就是S级别,当然MySQL使用间隙锁在RR级别就解决了这个问题) 网上很多文章提到幻读和提交读的时候,有的说幻读包括了delete的情况,有的说delete应该属于提交读的问题,那到底真相如何呢?我们实际来看下MySQL的官方文档(如下)
可以看到,幻读针对的是结果集前后发生变化,所以看起来delete的情况应该归为幻读,但是我们实际分析下上面列出的标准SQL在RR级别的实现原理就知道,标准SQL的RR级别是会对查到的数据行加行共享锁,所以这时候其他事务想删除这些数据行其实是做不到的,所以在RR下,不会出现因delete而出现幻读现象,也就是幻读不包含delete的情况。 MVCC能解决了幻读问题?网上很多文章会说MVCC或者MVCC+间隙锁解决了幻读问题,实际上MVCC并不能解决幻读问题。如以下的例子: begin; #假设users表为空,下面查出来的数据为空 select * from users; #没有加锁 #此时另一个事务提交了,且插入了一条id=1的数据 select * from users; #读快照,查出来的数据为空 update users set name='mysql' where id=1;#update是当前读,所以更新成功,并生成一个更新的快照 select * from users; #读快照,查出来id为1的一条记录,因为MVCC可以查到当前事务生成的快照 commit; 可以看到前后查出来的数据行不一致,发生了幻读。所以说只有MVCC是不能解决幻读问题的,解决幻读问题靠的是间隙锁。如下: begin; #假设users表为空,下面查出来的数据为空 select * from users lock in share mode; #加上共享锁 #此时另一个事务B想提交且插入了一条id=1的数据,由于有间隙锁,所以要等待 select * from users; #读快照,查出来的数据为空 update users set name='mysql' where id=1;#update是当前读,由于不存在数据,不进行更新 select * from users; #读快照,查出来的数据为空 commit; #事务B提交成功并插入数据 注意,RR级别下想解决幻读问题,需要我们显式加锁,不然查询的时候还是不会加锁的。
【相关推荐:mysql视频教程】 |
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!