Je rencontre un problème pour lequel je pense que le processus de réindexation du prix du produit est à l'origine d'une exception d'interblocage dans le processus de paiement.
J'ai attrapé cette exception dans le processus de commande:
Exception de conversion de commande: SQLSTATE [40001]: Échec de la sérialisation: 1213 Impasse trouvée lors de la tentative d'obtention du verrouillage; essayez de redémarrer la transaction
Malheureusement, je n'ai pas de trace de pile complète car l'exception a été interceptée, mais en vérifiant l'état INNODB, j'ai pu localiser l'impasse:
SELECT `si`.*, `p`.`type_id` FROM `cataloginventory_stock_item` AS `si`
INNER JOIN `catalog_product_entity` AS `p` ON p.entity_id=si.product_id
WHERE (stock_id=1)
AND (product_id IN(47447, 56678)) FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 329624 n bits 352 index
`PRIMARY` of table `xxxx`.`catalog_product_entity`
Le verrou de table demandant SQL est finalement généré à partir du Mage_CatalogInventory_Model_Stock::registerProductsSale()
moment où il tente d'obtenir le nombre d'inventaire actuel afin de le décrémenter.
Au moment où le blocage s'est produit, le processus de réindexation du prix du produit était en cours d'exécution et je suppose qu'il existait un verrou de lecture sur le catalog_product_entity table
qui a provoqué le blocage. Si je comprends correctement le blocage, tout verrou de lecture entraîne un blocage, mais le réindexage du prix du produit le verrouille pendant un temps raisonnable, car le site contient environ 50 000 produits.
Malheureusement, à ce stade du flux de code de paiement, la carte de crédit du client a été débitée (via un module de paiement personnalisé) et la création de l'objet de commande correspondant a échoué.
Mes questions sont:
- La logique du module de paiement personnalisé est-elle défectueuse? Par exemple, existe-t-il un flux accepté permettant à Magento de convertir le devis en une exception de commande sans frais préalable avant de valider le paiement par le moyen de paiement (carte de crédit)?
Edit: Il semble que la logique du module de paiement soit effectivement défectueuse, car l'appel à $ paymentmethod-> authorize () devrait avoir lieu après le lieu où cette impasse s'est produite, pas avant (comme l'indique la réponse d'Ivan ci-dessous). Cependant, la transaction sera toujours bloquée par l’impasse (même sans les frais erronés sur la carte de crédit).
Cet appel de fonction
$stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);
enMage_CatalogInventory_Model_Stock::registerProductsSale()
fait une lecture verrouillée, quel danger y aurait-il à en faire une lecture non verrouillable?En recherchant une réponse sur le Web, plusieurs endroits ont suggéré de ne pas exécuter une réindexation complète tant que le site est à chaud; semble à peine être une bonne solution; La question de l'indexation provoquant des blocages de table et des conflits de verrous est-elle un problème connu dans Magento? Existe-t-il des solutions de contournement?
Edit: Il semble que la question restante ici est celle de la troisième question; réindexation provoquant des blocages de table. Vous cherchez des solutions de contournement pour cela.
Edit: Le concept selon lequel les blocages ne sont pas des problèmes en soi, mais plutôt que la réponse à ces problèmes devrait être au centre des débats, a beaucoup de sens. Enquêtant plus avant pour trouver un point dans le code pour attraper l'exception d'interblocage et réémettre la demande. Faire cela au niveau de l’adaptateur de base de données Zend Framework est une approche, mais je cherche aussi un moyen de le faire dans le code Magento pour faciliter la maintenabilité.
Il y a un correctif intéressant dans ce fil de discussion: http://www.magentocommerce.com/boards/viewthread/31666/P0/ qui semble résoudre une situation de blocage similaire (mais pas celle-ci en particulier).
Edit: Apparemment, l’impasse a été corrigée dans CE 1.8 Alpha. Je cherche toujours une solution de contournement jusqu'à ce que cette version soit sortie de Alpha
Réponses:
Il est fort probable que votre méthode de paiement traite mal le paiement.
Le processus de sauvegarde des commandes Magento est assez simple:
checkout_type_onepage_save_order
etsales_model_service_quote_submit_before
Mage_CatalogInventory_Model_Stock::registerProductsSale()
est appelé à cet événement observateur$order->place()
méthode qui traite le paiement en appelant$paymentMethod->authorize()
,$paymentMethod->capture()
ou$paymentMethod->initialize()
dépend de sa logique.sales_flat_order_*
.Donc, comme vous le voyez, il est impossible que le mode de paiement charge l’argent avant le verrouillage des stocks et la lecture des prix ou des informations sur les produits.
Cela n’est possible que si le mode de paiement est implémenté de manière à charger les produits lui-même avec les prix, une fois que l’appel API pour la facturation a été effectué.
J'espère que cela vous aidera à résoudre votre problème.
Quant à la réindexation, elle devrait être sûre, si vous n’avez pas ce problème avec la méthode de paiement. Depuis l'opération de lecture, les verrous sont effectués avant que l'argent ne soit débité.
la source
registerProductsSale()
(comprendre que, avec les corrections apportées au module de paiement personnalisé, le problème de la facturation de la carte du client disparaîtra).S'agissant d'une extension personnalisée, nous pouvons trouver une solution de contournement personnalisée (read: hack) pour réessayer l'enregistrement sans modifier les fichiers de base.
J'ai résolu tous mes problèmes d'impasse avec les deux méthodes suivantes ajoutées à une classe d'assistance. Au lieu d'appeler,
$product->save()
j'appelle maintenantMage::helper('mymodule')->saferSave($product)
:Cela accomplit deux choses distinctes: il met en file d'attente une nouvelle tentative lorsqu'un blocage est rencontré et il définit un délai exponentiellement croissant pour cette nouvelle tentative. Il définit également le niveau d'isolation de transaction. Il existe de nombreuses informations sur SO et sur DBA.SE pour plus d'informations sur les niveaux d'isolation des transactions de MySQL.
FWIW, je n’ai pas rencontré d’impasse depuis.
la source
$tries
à cette fonctionsleep($this->getDelay());
Sur les forums Magento, ils parlent de l'édition d'un fichier de bibliothèque Zend: lib / Zend / Db / Statement / Pdo.php
La fonction _execute d'origine:
Après modification:
Comme vous pouvez le constater, la seule chose qui a changé est que le $ try a été déplacé en dehors de la boucle.
Comme toujours, il est suggéré de l'essayer sur un environnement de développement / test et de ne pas déployer instantanément ce correctif sur un environnement de production.
la source
J'ai le même problème sur un site Magento 1.11 et j'ai un ticket ouvert avec Magento dessus depuis le 11/12/2012. Ils ont confirmé qu'il s'agissait d'un problème et sont supposés créer un correctif.
Ma question est la suivante: pourquoi le prix doit-il être réindexé en ce moment? Je ne pense pas que cela soit nécessaire:
la source
Nous avons eu une impasse similaire lorsque certains appels ont été passés lors d'une réindexation. Pour nous, cela se manifestait surtout lorsqu'un client ajoutait quelque chose au panier. Bien que le problème sous-jacent réel ne soit probablement pas résolu, la mise en œuvre de la réindexation asynchrone a complètement stoppé tous les appels d'interblocage précédemment observés. Devrait fonctionner comme une pause jusqu'à ce que le problème sous-jacent soit résolu et transmis aux éditions EE / CE (nous avons fini par acheter une extension pour le faire).
la source
Je vous suggère d'installer Philwinkle DeadlockRetry. Cela a fonctionné pour notre base de données.
Je suggérerais également de regarder vos programmes extérieurs sur votre API Web. Nous en avions un qui mettait à jour la QTY pour les produits et causait de nombreuses impasses. Nous avons réécrit cela et sommes allés directement à la base de données.
la source
L’année dernière, j’ai rencontré plusieurs problèmes de blocage, j’ai réglé ce problème simplement en augmentant la mémoire de notre serveur, car le processus d’indexation consomme toutes les ressources.
Vous devriez également utiliser la solution de réindexation asynchrone que j'ai utilisée miravist
Pour un système plus stable, vous devriez penser à séparer votre serveur principal du serveur principal afin qu’ils ne mangent pas la RAM de l’autre.
Pour mon expérience, ce n'est pas un problème de code source.
la source