mysql采用默认事务隔离级别REPEATABLE-READ;
然后我分别执行以下内容:
1、
2、使用jdbc访问数据库:
3、这时候打印结果,发现线程进入阻塞,一直卡在这里
也就是说我开启的另一个事务仍然能读取到数据,只是在最后执行executeUpdate的时候才被锁定不能执行
4、命令行执行commit
5、结果命令行操作被jdbc操作替换掉,数据改为4。
这不就是说REPEATABLE-READ仍然出现了丢失更新,而且没有行锁定吗?
事务与并发到底是什么区别,我在测试多线程执行以上jdbc操作时,发现最后得到的结果总是不对。例我开十个线程,每个都对数据+1,结果可能只加了5.所以在并发情况下怎么做才能保证数据的安全?
S'il n'est augmenté que de un, la valeur de number ne sera pas obtenue via select, et la valeur obtenue par select peut être l'ancienne valeur, puis remplacez-la par update test set number = number 1 où id = ? . Le numéro ici sera le plus récent. Cette méthode peut éviter la perte complète des performances série de la sélection pour la mise à jour.
REPEATABLE-READ peut provoquer des lectures fantômes
Si vous souhaitez garantir une sécurité absolue, vous ne pouvez définir le niveau d'isolement que sur SERIALIZABLE
De cette façon, toutes les transactions ne peuvent être exécutées que séquentiellement, et naturellement il y aura aucun problème dû à la concurrence. Cela est affecté, mais les performances chuteront beaucoup.
Si vous ne voulez pas que les performances baissent mais que vous souhaitez également les contrôler afin que cela ne se passe pas mal, une approche plus courante consiste désormais à utiliser un contrôle de version plus récent.
Conservez un champ comme UpdateVersion. Lors de la modification, updateversion est également transmis en tant que paramètre. Ajoutez par exemple
where id=? and update_version = ?
dans l'instruction conditionnelle. Bien sûr, update_version 1 est requis dans l'ensemble.Cela peut être contrôlé afin qu'une seule personne puisse mettre à jour une version à la fois.
Grâce à des expériences, j'ai découvert que j'avais dans une certaine mesure compris mon problème.
J'ai déjà été induit en erreur par des informations erronées sur le niveau d'isolement des transactions, pensant que le niveau REPEATABLE-READ et le niveau SERIALIZABLE peuvent résoudre le problème des mises à jour perdues, mais en fait ce n'est pas le cas.
Parce que l'instruction select ... from table; de mysql ne bloquera pas quel que soit le niveau d'isolement,
Sous le niveau d'isolement, le verrou en écriture (verrouillage exclusif) n'attendra la publication que lors de la mise à jour des données, de sorte que plusieurs threads peuvent lire le nombre = 3 en même temps. Les modifications basées sur cela entraîneront inévitablement des mises à jour perdues.
La solution est donc d'ajouter un mécanisme de verrouillage pessimiste ou optimiste au programme.
Le verrouillage pessimiste utilise select ... pour la mise à jour,
À ce stade, l'opération de lecture de la transaction B ne sera pas exécutée. Ce n'est que lorsque la validation de la transaction A est terminée que la transaction B peut continuer à s'exécuter, ce qui équivaut à une exécution en série une par une.
Le verrouillage optimiste est couramment utilisé pour le contrôle de version ou le contrôle d'horodatage,
À ce moment-là, la transaction B a découvert que version=1 n'existe plus, car la transaction A a d'abord terminé l'exécution et mis à jour la base de données, en définissant le champ de version sur 2. Cela entraînera l'échec de la soumission de la transaction, et nous devons déterminer la situation anormale dans le programme. Comment procéder ci-dessous.
Ce qui précède est ma compréhension actuelle. Quant au MVCC (Multiple Version Concurrency Control) pris en charge par MySQL lui-même, je ne sais toujours pas comment l'utiliser, je ne sais pas comment implémenter la gestion des exceptions du verrouillage optimiste. . Cela peut être basé sur des scénarios commerciaux spécifiques. Utilisez une approche différente.
S'il s'agit d'un simple
Select
, il sera considéré comme une simple opération de requête, il ne sera donc pas suspendu.Si vous souhaitez effectuer une transaction sur une certaine ligne, vous devez d'abord utiliser le format
Select
lorsqueSelect ... For Update
.L'utilisation de
For Update
verrouillera la ligne sélectionnée Lorsqu'une autre transaction est effectuée, elle sera suspendue auSelect ... For Update
de cette transaction et attendra la fin de la transaction en cours avant de continuer. Cela garantit qu’il n’y a pas d’intermédiaire entre l’interrogation et l’écriture.Contrôlé par serrure.