当前位置:网站首页>Auto - vérification recommandée! Les bogues MySQL ne font pas reculer les transactions, peut - être êtes - vous à risque!
Auto - vérification recommandée! Les bogues MySQL ne font pas reculer les transactions, peut - être êtes - vous à risque!
2022-06-23 14:29:00 【Canal de programme DD】

Auteur:KLBlogueurs
Source::https://my.oschina.net/klblog/blog/5542934
Sur la question de la non - rétrocession des transactions,On en a déjà parlé.:
Partager unOpen Source Document Online Preview Project SolutionkkFileViewUne mise à jour de l'auteur.
Comme le titre,Le problème a finalement été identifié parce que mysql-connector-java:8.0.28 Un bug Résultat.Mais avant que la vérité n'apparaisse,,Toute la question est confuse.,Le blogueur n'a pas vérifié si fort depuis longtemps. bug ,Avec des couches debug En profondeur,La vérité est apparue..C'est une question de bas niveau. jdbc Problèmes de conduite,Universel,Peut - être inconsciemment.,Votre application souffre également de cela en ligne bug De la destruction,Alors..., S'il vous plaît, écoutez - moi bien. , Puis retournez vérifier l'état de votre application , Est - ce que j'ai aussi marché sur la fosse . Comme direct peut être tiré directement à la fin de l'article pour voir le résultat .
Contexte
La narration commence généralement par les personnages 、Contexte. Il n'y a pas d'exception ici , Présentez d'abord les parties intéressées. .En général, Plus l'histoire est riche, plus elle est merveilleuse. , Mais ici, les blogueurs pensent à l'espace (Pas de conneries.) Les détails qui n'ont rien à voir avec l'orientation des résultats seront ignorés , Essaie d'être complet. .
commons-db : Notre entretien interne , Un moteur d'annotation Spring Composantes de la gestion des sources de données multiples dans un contexte écologique . Composants pour chaque DataSource Par défaut avec quelques optimisations de performance , Pas tout listé , Mais contient des attributs qui influencent l'orientation du problème (useLocalSessionState),Comme suit:
Properties defaultProperties = new Properties();
defaultProperties.put("prepStmtCacheSize", 300);
defaultProperties.put("prepStmtCacheSqlLimit", 2048);
defaultProperties.put("useLocalSessionState", true);
defaultProperties.put("cacheResultSetMetadata", true);
defaultProperties.put("elideSetAutoCommits", true);java-project : Éléments utilisés pour tester la fonctionnalité des composants , Les tests de comportement sont comparés aux éléments problématiques .spring-boot:2.5.4、mysql-connector-java:8.0.26
store: Projet de bibliothèque de jeux , C'est ce projet qui a trouvé le problème. .spring-boot:2.6.6 、mysql-connector-java:8.0.28
Alicloud RDS (MySQL): Alicloud MySQL Le niveau d'isolement par défaut est READ_COMMITTED,Et MySQL Le niveau d'isolement par défaut est REPEATABLE_READ
Description:java-project Et store De commons-db Les versions sont différentes , Parce que ça n'affecte pas les résultats . Supposons qu'ils soient identiques. .
Questions
Un jour., Développer la rétroaction ,In store Utilisé dans le projet commons-db Composants, Il y a eu un problème avec le report de transaction non efficace .Comme le montre le code ci - dessous:
@Transactional
@DataSource(type = Type.MASTER,value = "developer")
public void addUser(ApolloUser user){
userRepository.save(user);
int i = 1/0; //Lancer une exception
}En particulier::Mise en œuvre addUser Méthodes,Quand 1/0 Jetez RuntimeException Lorsque le type est anormal ,user Objet ajouté avec succès .En résumé,【 Le ROLLBACK des transactions n'est pas valide 】.
Hypothèses
Hypothèses 1: J'ai supposé que c'était @Transactional De aop Ça n'a pas marché, Provoque une transaction explicite non ouverte .
Hypothèses 1 C'est faux., Parce que c'est ouvert debug Après le mode log , Sortie claire du Journal de comportement pour chaque étape de la transaction ,Par exemple::

Hypothèses 2: Compte tenu de l'utilisation commons-db , Si vous avez des problèmes de gestion de la connectivité au niveau du cadre , Provoque l'ouverture de la transaction 、 La connexion obtenue lors du retournement de transaction est incohérente , Ça pourrait aussi causer ce problème. .
Hypothèses 2 C'est faux.: Pas tout de suite. , Parce que le journal ci - dessus montre que la connexion est la même . Et différentes connexions s'ouvrent de façon inattendue 、 L'opération de report d'une transaction devrait lancer une exception. .
Alors viens ici., La question est dans l'impasse . Je ne peux m'empêcher de réfléchir. , Un code qui semble inoffensif pour les humains et les animaux. , Un journal des transactions apparemment logique , Pourquoi la transaction a - t - elle échoué? ?????
Transfert
Transfert 1
Par la suite,Je suis java-project Dans le projet,Utiliser le même MySQL Testé., La transaction a été reportée avec succès . Indique que le problème n'affecte que des environnements spécifiques , Et on peut trouver des problèmes en comparant les différences entre les deux projets , Plus près de la vérité .
Transfert 2
Un autre message clé est venu du côté du développement. ,In store Dans le projet, Lorsque le niveau d'isolement est défini à REPEATABLE_READ Heure, Le ROLLBACK de transaction est en vigueur .Code comme:
@Transactional(isolation = Isolation.REPEATABLE_READ)
@DataSource(type = Type.MASTER,value = "developer")
public void addUser(ApolloUser user){
userRepository.save(user);
int i = 1/0;
}Par ici., Mais est - ce une question de niveau d'isolement? ?Apparemment pas., Parce que dans le dictionnaire cognitif des transactions, , Il n'y a pas eu de mot où le niveau d'isolement a affecté le retour en arrière de la transaction .Et de java-project Les tests de ,Dans le même RC Niveau d'isolement inférieur,java-project Ça peut marcher..
La première solution
Et c'est un pas en avant. , Peut être résolu temporairement en fixant un niveau d'isolement 【 Problème d'inefficacité du report des transactions 】.Mais,Différents niveaux d'isolement, Verrouillage des transactions 、 Les performances simultanées sont différentes , Il faut s'y attendre avant de procéder à un ajustement. .
Transfert 3
Si quelque chose tourne mal, il doit y avoir un démon., Dans l'esprit de l'incrédulité, c'est le niveau d'isolement qui cause le problème. ,Je suis store Dans le cadre du projet isolation Set to Isolation.READ_UNCOMMITTED , Le ROLLBACK des transactions est également en vigueur . Cela signifie également qu'il n'y a pas de relation directe avec le niveau d'isolement . Et ensuite, dans l'exploration 【 Pourquoi par défaut READ_COMMITTED Faire en sorte que la transaction ne prenne pas effet?】 J'ai vérifié , J'ai trouvé des problèmes , Le code suivant fait partie de la logique de transaction (Code source voir:DataSourceUtils.prepareConnectionForTransaction ()):

Découverte,Comparé à RR、RU , La différence est quand le niveau d'isolement est READ_COMMITTED Heure, - Non. session Il y a une opération de mise à jour . Ce n'est qu'un phénomène de plus , Peut expliquer le comportement après avoir appris la vérité , N'a pas atteint le bord de la vérité .
Analyse
Tout ce qui précède , Pas de vrai problème. . Alors ne fais pas d'autres tests. , D'abord, il y a des attentes. , Dans la validation ciblée .
Commençons par la normale générale. Spring Transactional Processus complet de report des transactions , Ce qui est courant, c'est qu'il n'y a pas de configuration spéciale des paramètres , En général, ces paramètres ne sont pas configurés .
1、Ajouté @Transactional Avant l'exécution de la méthode , Le gestionnaire de transaction sera exécuté (DataSourceTransactionManager)De doBegin Méthode créer une transaction,In doBegin Méthode,Va mettre en place autoCommit = false. Détermine si le niveau d'isolement actuel est conforme à la définition de l'utilisateur , Sinon, le niveau d'isolement est mis à jour .

2、 Après l'échec de l'exécution de la méthode , Le gestionnaire de transaction sera exécuté (DataSourceTransactionManager)De doRollback Méthode ROLLBACK transaction.
De Spring Transactional Le Journal des transactions de ,Créer une transaction、Mise en place d'une transaction manuelle、 Toutes les transactions de ROLLBACK ont une impression de journal . Alors nous allons aller plus loin dans la couche d'entraînement 、 Ou prendre un sac. , Si toutes ces instructions sont envoyées à MySQL Server C'est.
Problèmes de positionnement
Comme l'analyse,In store Dans le projet,Tapez le point d'arrêt à mysql-connector-java Conduite NativeSession.execSQL () Méthode,Et MySQL Server Toutes les instructions d'interaction , Cette méthode est finalement appelée à exécuter .J'ai trouvé le problème:
Lorsque la transaction a échoué , Le processus de transaction n'a pas été exécuté SET autocommit=0 Directives.
égal à dire que la transaction a échoué , Les transactions ont toujours été soumises automatiquement ,Alors..., Une opération de ROLLBACK anormale ne fait pas reculer les données qui ont été persistantes .
Après avoir découvert ce problème, Ensuite, localisez pourquoi Spring Mise en œuvre Set autoCommit=false , Questions qui n'ont finalement pas été mises en œuvre ,Encore une fois【Transfert 1】De java-project Comparaison de la mise en service en une seule étape du projet ,J'ai trouvé un code clé(ConnectionImpl.setAutoCommit ()) Code incohérent dans les deux projets :
java-project,mysql-connector-java:8.0.26( Le ROLLBACK des transactions prend effet )

store,mysql-connector-java:8.0.28( Le ROLLBACK de transaction n'est pas valide )

Voici un aperçu de ce paramètre
useLocalSessionState: Entretien local sessionState , Au besoin de jugement 【 Mode de soumission des transactions 】、【Niveau d'isolement】Lors du réglage, Obtenir l'état local , Au lieu d'être comme MySQL Server Demander.
Ce paramètre aide à réduire et MySQL L'interaction de, Améliore les performances d'écriture des données . Ainsi, lors de l'optimisation des performances des paramètres , Par défaut à true C'est.Ici.,Si useLocalSessionState=false, C'est ce qui va masquer ça. bug.
Décrypter
Parce que store,mysql-connector-java:8.0.28 La version en question isAutocommit () Logique comportementale et isAutoCommit () Incohérence, J'aurais dû appeler le juge isAutocommit Retour true Heure,Et il est revenu false. C'est ce qui a mené à store Reçu Spring Transactional Paramètres autoCommit=false Sur demande,Parce que needsSetOnServer=false , Sauter le vrai lancement Set autocommit=0 Mise en œuvre de la directive. Fait en sorte que le mode de transaction actuel soit le mode d'engagement automatique , Donc quand il y a des ajouts, des suppressions et des modifications dans la transaction , Dès que l'exécution sera terminée commit Persistance. Dans ce cas, la transaction est lancée en cas d'exception rollback , Naturellement, il n'y a pas de retour en arrière d'une transaction qui a déjà été engagée automatiquement . C'est une bonne explication que le Journal des transactions affiché au début est complet , Mais la transaction est un problème de retour en arrière inefficace .
Deuxième solution
J'ai vérifié ici., La deuxième solution est venue. , Il suffit de laisser le jugement s'exécuter Set autocommit=0 Heure needsSetOnServer=true Ça suffit. .Alors...,Tant que c'est vrai store Appliquer l'un ou l'autre des deux paramètres suivants pour le réglage de la configuration des paramètres , Ça résoudra le problème. . C'est mieux que la première. :
useLocalSessionState=false
auto-commit=falsePourquoi? isolation Set to Isolation.REPEATABLE_READ Ça marchera.
Alors c'est fini ici? ?Non., On s'attend à ce que même useLocalSessionState=ture , La transaction devrait aussi être complète .Et n'oublie pas isAutoCommit () Et isAutocommit () Différences. Commençons par leur définition. :
public boolean isAutocommit() {
return (this.statusFlags & 2) != 0;
}
public boolean isAutoCommit() {
return this.autoCommit;
}C'est vrai. mysql-connector-java:8.0.28 Drive in,Utiliser statusFlags État remplacé autoCommit Identification( On ne se demande pas pourquoi on a fait ce changement. ), Voilà l'explication.
Transfert 2: Lorsque le niveau d'isolement est défini à REPEATABLE_READ Heure, Le ROLLBACK de transaction est en vigueur . Parce que lorsque le niveau d'isolement défini par l'utilisateur RR Et par défaut RC En cas d'incohérence,Ça va déclencher session Définir un nouveau niveau d'isolement ,À ce stade statusFlags = 0 Mise à jour vers statusFlags = 2. Donc C'est un appel isAutocommit () Retour true , Mise en œuvre satisfaisante SET autocommit=0 Conditions de la directive .
Je sais pourquoi. , Et je sais exactement isAutoCommit () != isAutocommit () , Mais il n'est pas clair pourquoi cela a été fait. . Les questions spécifiques ne sont pas énumérées ici pour le moment. ,Revenons à la question.
Question de la récurrence
Maintenant que le problème est bien réglé, , Ensuite, suivez le processus de dépannage normal , Réapparaître comme prévu , Définir les limites du problème . Parce qu'il peut y avoir d'autres facteurs d'influence qui peuvent causer des problèmes ensemble .In java-project Dans le projet, Effectuer les ajustements de version suivants pour les dépendances
Mise à jour spring-boot:2.6.6 Version et store Soyez cohérent: Le problème revient.
Tiens bon. spring-boot:2.5.4,Ajustement mysql-connector-java:8.0.28 : Le problème est revenu
Par ici., C'est pratiquement exclu. Spring Transactional C'est suspect. . Et il a verrouillé la lance. mysql-connector-java:8.0.28 Sur le corps..
Confirmation bug
Compte tenu du fait que mysql-connector-java:8.0.26 De isAutoCommit A changé mysql-connector-java:8.0.28 De isAutocommit Il doit y avoir une raison, Avec l'intention de clarifier l'auteur du Code pour soumettre ce changement , Je l'ai renversé. github.
https://github.com/mysql/mysql-connector-j
J'ai trouvé. github Documents soumis pour commit ,Découverte, La dernière version a été modifiée. isAutoCommit () C'est,Et puis Commit Message Il est clair que c'est 8.0.28 Version bug,Par exemple:.

Jusqu'ici., Enfin, la vérité s'est révélée .
Réparation
8.0.29 release:https://dev.mysql.com/doc/relnotes/connector-j/8.0/en/news-8-0-29.html
A connection did not maintain the correct autocommit state when it was used in a pool with
useLocalSessionState=true. (Bug #106435, Bug #33850099)
Solution finale
Par exemple: 8.0.29 release Notes d'annonce ,Réparé. 8.0.28 Dans la configuration useLocalSessionState=true Dans le cas de,autoCommit Problème avec le réglage de l'état .Alors..., Mise à jour de l'application vers mysql-connector-java:8.0.29 La version est OK.
Conclusion
Résumez d'abord le tableau des questions comme suit: Spring Transactional【 Le ROLLBACK de transaction n'est pas valide , Les données soumises avant le ROLLBACK ne sont pas rollback 】,La raison fondamentale est 【mysql-connector-java:8.0.28 Une modification soumise par la version bug , Provoque l'activation useLocalSessionState=true Dans le cas de,autoCommit Il y a un problème avec le réglage de l'état 】.
Et parce que spring-boot:2.6.3 ~ 2.6.7 , Par défaut pour ces cinq versions MySQL L'entraînement est mysql-connector-java:8.0.28 ,Et useLocalSessionState=true Presque. Java JDBC DataSource Standard in,Donc ça bug On estime qu'une vague de personnes . Et parce que ça n'affecte que l'opération de rollback , C'est pourquoi cette question est très cachée. , Pas facile à détecter , Ce qu'on appelle l'influence profonde .
Enfin, Envoyer cet article prend en charge l'auteur , En même temps, faire connaître le problème à un plus grand nombre de petits partenaires et le traiter à l'avance , Évitez l'embarras d'être appelé au milieu de la nuit !
Nous avons créé un groupe d'échanges techniques de haute qualité,Avec les bons,Moi aussi, je serai meilleur,Dépêchez - vous.Cliquez sur Ajouter un groupe,Profitez du bonheur de grandir ensemble.En plus,Si tu veux changer d'emploi récemment,J'ai dépensé2Une grande vague de sutras a été recueillie au cours de la semaine,Celui qui est prêt à changer d'emploi après le festival peutCliquez ici pour recevoir!
Lectures recommandées
··································
Bonjour,Je suis un singe programmé.DD,10Développer de vieux conducteurs、AlicloudMVP、Tencent CloudTVP、J'ai fait des livres et des affaires、Entreprises publiques4Année Internet6Année.Du développement ordinaire à l'architecte、Aux partenaires.Tout le chemin,Ce qui m'a le plus impressionné, c'est de continuer à apprendre et à me concentrer sur les frontières.Tant que tu peux tenir,Pense plus、Ne te plains pas.、Fais - le souvent,C'est facile de dépasser les virages!Alors...,Ne me demandez pas si je peux faire quelque chose maintenant.Si vous regardez une chose,J'ai dû insister pour voir l'espoir,Au lieu de voir l'espoir persister.Fais - moi confiance.,Tiens bon,Tu dois être meilleur que maintenant!Si vous n'avez pas encore de direction,Je peux d'abord me concentrer sur moi,Voici souvent des informations de pointe,Pour vous aider à accumuler des capitaux pour le dépassement de virage.
Cliquez pour recevoir2022Mise à jour10000TMatériel d'apprentissage
边栏推荐
- [in depth understanding of tcapulusdb technology] tcapulusdb business data backup
- Linear regression analysis of parent-child height data set
- Quick view of wechat applet development process
- 微信小程序之获取php后台数据库转化的json
- AI talk | data imbalance refinement instance segmentation
- The first public available pytorch version alphafold2 is reproduced, and Columbia University is open source openfold, with more than 1000 stars
- 【深入理解TcaplusDB技术】单据受理之表管理
- 等保备案是什么意思?应该去哪里办理备案?
- When did the redo log under InnoDB in mysql start to perform check point disk dropping?
- The data value reported by DTU cannot be filled into Tencent cloud database through Tencent cloud rule engine
猜你喜欢

ICML 2022 𞓜 context integrated transformer based auction design neural network

【深入理解TcaplusDB技术】TcaplusDB构造数据

【二级等保】过二级等保用哪个堡垒机品牌好?

Crmeb second open SMS function tutorial

Unity realizes the function of playing Ogg format video

渗透测试-提权专题

Working for 7 years to develop my brother's career transition test: only by running hard can you get what you want~

【深入理解TcaplusDB技术】单据受理之表管理

Vulnhub target os-hacknos-1
![[deeply understand tcapulusdb technology] tmonitor background one click installation](/img/0a/742503e96a9b51735f5fd3f598b9af.png)
[deeply understand tcapulusdb technology] tmonitor background one click installation
随机推荐
Wechat applet pop up the optional menu from the bottom
【深入理解TcaplusDB技术】Tmonitor系统升级
High quality coding - air quality map visualization
Intelligent digital signage solution
JSP_ SSM Wanfu cinema ticket sales management system, including paper [demonstration video]
Problems during MySQL uninstallation
vulnhub靶机Os-hackNos-1
大厂架构师:如何画一张大气的业务大图?
Drop down menu scenario of wechat applet
【深入理解TcaplusDB技术】Tmonitor后台一键安装
Soaring 2000+? The average salary of software testing in 2021 has come out, and I can't sit still
Penetration test - right raising topic
The data value reported by DTU cannot be filled into Tencent cloud database through Tencent cloud rule engine
Kali use
From the establishment to the actual combat of the robotframework framework, I won't just read this learning note
[in depth understanding of tcapulusdb technology] tcapulusdb business data backup
Ks003 mall system based on JSP and Servlet
Technology sharing | do you understand the requirements of the tested project?
今年英语高考,CMU用重构预训练交出134高分,大幅超越GPT3
How to make food nutrition label