10
votes

InnoDB Sélectionnez ... Pour Mettre à jour le relevé Verrouillage de toutes les lignes dans une table

Version MySQL Server 5.1.41 avec plug-in InnoDB activé. J'ai les trois tables suivantes pour les factures: factures, invoices et facturations et factures_expensens. Les factures de table ont une clé primaire sur invoice_id. Les deux factures_Components et FIVOICE_EXPENSESPENSESPENSES sont liés aux factures de table avec FIVOICE_ID comme étrangère non unique (chaque facture peut avoir plus d'un composant et plus d'une charge). Les deux tables ont un indice BTRee pour cette clé étrangère.

J'ai les transactions suivantes:

transaction 1 xxx

Tout fonctionne correctement pour la première transaction et les lignes sont sélectionnés et verrouillés.

transaction 2 xxx

La seconde transaction renvoie Erreur 1205 (HY000): le délai d'attente de verrouillage dépassé; Essayez de redémarrer la transaction pour la troisième requête.

La même chose se produit lorsque j'essaie de choisir ... pour mettre à jour les autres factures et leurs composants et leurs dépenses. Il semble que la première transaction ait verrouillé toutes les lignes de la table Invoice_expenses. Toutes idées pourquoi cela se produit?

Info supplémentaire

transaction 2 commence après la troisième requête de transaction 1. Il n'y a pas d'autres utilisateurs, connexions ou transactions Sur le serveur.

Le problème se produit dans le niveau d'isolation de transaction de lecture répétable par défaut. Il est corrigé en passant au niveau de la lecture du niveau engagé. C'est une solution, mais cela n'explique toujours pas pourquoi le problème se produit avec fact_expenses et non avec fact_components.


12 commentaires

Êtes-vous sûr que tous les enregistrements sont verrouillés? InnoDB peut verrouiller les enregistrements de quartier (lorsque vous verrouillez-vous entre 18 et 19 et 19), mais ne devrait pas verrouiller les enregistrements qui sont loin d'Awat dans le Btree - alors essayez-le avec une plus grande distance dans les identifiants? En outre, quel est votre niveau d'isolement?


@Darhazer. Merci. Changer le niveau d'isolement pour lire le problème résolu le problème. Pouvez-vous expliquer ce qui se passait? MySQL Gap a-t-il verrouillage de la table FIVOICE_EXPENSESPENSES? Pourquoi la même chose n'a-t-elle pas eu lieu avec facturation_components? Quoi qu'il en soit, si vous postez une réponse, je l'accepterai.


Je n'ai pas de réponse pourquoi cela se passe dans la lecture répétable, je préfère donc mettre une prime sur la question que de poster une réponse incomplète. Est-ce que ceux-ci sont les seules requêtes exécutées dans les transactions? La deuxième transaction a-t-elle été démarrée après avoir effectué la troisième requête dans la première transaction, ou elles sont simultanées? Je vais ajouter une prime après les 2 jours requis par ainsi


Je vais ajouter tout comme des informations supplémentaires pour la question. Merci pour l'aide.


Jut se demandant. Que se passe-t-il si vous définissez niveau d'isolement sur sérialisable ?


Je soupçonne que cela a à voir avec le lecture répétable : "pour verrouillage des lectures (sélectionnez-la avec Mettre à jour ou verrouillage en mode Share), mettre à jour et supprimer des instructions, le verrouillage dépend de la question de savoir si l'instruction utilise Un index unique avec une condition de recherche unique ou une condition de recherche de type plage. Pour un index unique avec une condition de recherche unique, l'innoDB verrouille uniquement l'enregistrement d'index trouvé, pas l'écart avant de cela. Pour d'autres conditions de recherche, Innodb Verrouille la plage d'index numérisée, à l'aide de verrous de l'espace libre ou de clé Next-Key (enregistrement d'index de l'index de l'index de l'espace libre) pour bloquer les insertions par d'autres sessions dans les lacunes couvertes par la plage . "


... Comportement, et le Lire commité Comportement: "Remarque Dans MySQL 5.1, si le niveau d'isolement enregistré est utilisé ou la variable système Innodb_Locks_unsafe_for_binlog est activé, Il n'y a pas d'innoDB Verrouillage de l'écart Sauf pour la vérification des contraintes de clé étrangère et la vérification des touches en double. De plus, Les serrures d'enregistrement pour les lignes non amorties sont publiées après que MySQL ait évalué la condition . "


(Ce qui précède provient de: dev.mysql.com/doc/ Refman / 5.1 / fr / set-transaction.html )


@ Miloš Rašić Pouvez-vous ajouter le résultat de "Expliquer" pour vérifier la théorie @ypercube? Ainsi que vérifier si le résultat est le même dans Serializable? @YPERCUBE Postez-le comme une réponse, il peut donc être récompensé.


Ce que j'aimerais tester (je n'ai pas le temps maintenant), c'est si cette chose se passe avec des identifiants non séquentiels, comme 18 et 20 ou 18 et 99 . Si cela se produit toujours, je suppose que cela a à voir avec les "écluses d'écart et les serrures suivants" est probablement faux.


@ Milošrašić Avez-vous trouvé votre réponse sur la raison pour laquelle cela se produit?


@ Milošrašić et pouvez-vous aussi me montrer vos index de table?


3 Réponses :


-2
votes

Vous utilisez une transaction; AutoCommit ne désactive pas les transactions, il les fait simplement commettre automatiquement à la fin des déclarations qui ne disposent pas d'une transaction explicite sur eux.

Ce qui se passe est, un autre thread contient une serrure d'enregistrement sur certains enregistrements (vous mettez à jour chaque enregistrement dans la table!) Pour trop longtemps, et votre fil est expiré.

Vous pouvez voir plus de détails sur l'événement en émettant un «Statut Innodb Innodb» de «Show Moteur» après l'événement. Faites-le idéalement sur un test silencieux.


1 commentaires

Désolé, précipitez-vous, vous n'avez pas lu ma question en détail ou que vous ne l'avez pas très bien compris. Je garde la première transaction ouverte exprès pour tester la concurrence. Le problème est qu'il s'agit de lignes de verrouillage qu'il ne sélectionne pas dans la table Invoice_expensenspenses. Ceci est sur un serveur de développement, il n'y a donc aucun autre utilisateur, connexions ou transactions. Utilisez déjà le statut Innodb Moteur Show Moteur.



11
votes

Je soupçonne que cela a à voir avec verrouillages d'écart et verrouillons suivants et les différences dans le comportement de lecture répétable :

Les extraits sont originaires de MySQL Docs: Définir la transaction Syntaxe

Pour verrouillage des lectures (sélectionnez avec Mettre à jour ou verrouillage en mode Share), mettez à jour et supprimer des instructions, le verrouillage dépend de la question de savoir si l'instruction utilise un index unique avec une condition de recherche unique ou une condition de recherche d'une plage. Pour un index unique avec une condition de recherche unique, Innodb verrouille uniquement l'enregistrement d'index trouvé, pas l'écart avant de cela. Pour d'autres conditions de recherche, InnoDB verrouille la gamme d'index numérisée, à l'aide de verrous blinds ou de clé Next Plus (enregistrement de l'index de l'index de la touche NEXT plus (FORT> pour bloquer les insertions par d'autres sessions dans les lacunes couvertes par la gamme.

et lu engagé :

Remarque: Dans MySQL 5.1, si le niveau d'isolement enregistré est utilisé ou que la variable système Innodb_Locks_unsafe_for_binlog est activée, Il n'y a pas de verrouillage de l'écart InnoDB à l'exception de la vérification des contraintes de clé étrangère et de la vérification de la clé en double . De plus, Les serrures d'enregistrement pour les lignes non amassantes sont libérées après que MySQL ait évalué la condition de la situation.

peut-être op peut nous dire le statut de innodb_locks_unsafe_for_binlog System Variable et si le même verrouillage se produit lorsque le réglage de cette variable est modifié.

Également, si le même verrouillage se produit avec des identifiants non séquentiels, comme 18 et 20 ou 18 et 99


3 commentaires

Mon innodb_locks_unsafe_for_binlog est désactivé. J'ai les mêmes résultats lors du verrouillage des lignes pour ID 18 et d'essayer de sélectionner pour les lignes de mise à jour pour ID 21. Il n'y a pas d'identifiant 20.


@ Miloš: Et si vous définissez innodb_locks_unsafe_for_binlog sur ON? Est-ce que ça arrive encore?


Nous ne pouvons pas encore savoir si cela cause le problème, mais votre réponse est utile pour moi et est la seule qui fournit des idées, donc je vous accordons la prime. J'espère que OP continuera de tester et nous trouverons la cause fondamentale.



0
votes

"Pour Index enregistre les rencontres de recherche, sélectionnez ... Pour les blocs de mise à jour des blocs d'autres sessions de la section Sélectionnez ... Verrouillage en mode de partage ou en lecture dans certains niveaux d'isolation de transaction. Lectures cohérentes Ignorer les verrous définis sur les enregistrements existants dans la vue de lecture "

Quels sont ces certains verrouillons pouvant être appliqués avec Sélectionner pour la mise à jour afin que d'autres sessions ne puissent pas lire un enregistrement verrouillé?


0 commentaires