Ich habe ein Problem, bei dem der Prozess der erneuten Indizierung des Produktpreises meines Erachtens eine Deadlock-Ausnahme im Checkout-Prozess verursacht.
Ich habe diese Ausnahme beim Auschecken festgestellt:
Ausnahme bei der Auftragskonvertierung: SQLSTATE [40001]: Serialisierungsfehler: 1213 Deadlock beim Versuch, eine Sperre abzurufen; Starten Sie die Transaktion erneut
Leider habe ich keinen vollständigen Stack-Trace, da die Ausnahme abgefangen wurde, aber ich habe den INNODB-Status überprüft und konnte den Deadlock aufspüren:
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`
Die SQL-Anfragetabellensperre wird letztendlich generiert, Mage_CatalogInventory_Model_Stock::registerProductsSale()
wenn versucht wird, die aktuelle Inventurzählung abzurufen, um sie zu dekrementieren.
Zu dem Zeitpunkt, als der Deadlock auftrat, wurde der Produktpreis-Neuindexierungsprozess ausgeführt, und ich gehe davon aus, dass er eine Lesesperre für die hatte catalog_product_entity table
, die den Deadlock verursacht hat. Wenn ich den Deadlock richtig verstehe, wird durch jede Lesesperre ein Deadlock ausgelöst, aber der Produktpreis-Neuindex hält die Sperre für eine angemessene Zeit aufrecht, da auf der Site ~ 50.000 Produkte vorhanden sind.
Leider wurde zu diesem Zeitpunkt im Bestellcode-Fluss die Kreditkarte des Kunden belastet (über ein benutzerdefiniertes Zahlungsmodul), und die Erstellung des entsprechenden Bestellobjekts schlug fehl.
Meine Fragen sind:
- Ist die Logik des benutzerdefinierten Zahlungsmoduls fehlerhaft? Dh Gibt es einen akzeptierten Ablauf, um sicherzustellen, dass Magento das Angebot in eine Bestellungsausnahme umwandeln kann, bevor die Belastung der Zahlungsmethode (Kreditkarte) zugewiesen wird?
Bearbeiten: Es scheint, dass die Logik des Zahlungsmoduls tatsächlich fehlerhaft ist, da der Aufruf von $ paymentmethod-> authorize () nach dem Ort erfolgen sollte, an dem dieser Deadlock auftritt, und nicht vorher (wie in der Antwort von Ivan unten angegeben). Die Transaktion wird jedoch weiterhin durch den Deadlock blockiert (allerdings ohne die fehlerhafte Belastung der Kreditkarte).
Dieser Funktionsaufruf
$stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);
inMage_CatalogInventory_Model_Stock::registerProductsSale()
macht es zu einem Sperr lesen, wie gefährlich es wäre es ein nicht sperr gelesen werden , um zu machen?Beim Durchsuchen des Webs nach einer Antwort haben einige Stellen vorgeschlagen, keine vollständige Neuindizierung durchzuführen, solange die Site noch in Betrieb ist. scheint kaum eine gute Lösung zu sein; Ist das Problem der Indizierung, das zu Tabellen-Deadlocks und Sperrenkonflikten führt, in Magento ein bekanntes Problem? Gibt es Problemumgehungen?
Bearbeiten: Es scheint, die verbleibende Frage hier ist die aus der dritten Frage; Neuindizierung führt zu Table Deadlocks. Suchen Sie nach Problemumgehungen dafür.
Bearbeiten: Das Konzept, dass Deadlocks nicht an sich Probleme sind, sondern die Reaktion auf sie im Mittelpunkt stehen sollte, ist sehr sinnvoll. Weitere Untersuchungen, um einen Punkt im Code zu finden, um die Deadlock-Ausnahme abzufangen und die Anforderung erneut auszustellen. Dies auf der Ebene des Zend Framework DB-Adapters zu tun, ist ein Ansatz, aber ich suche auch nach einer Möglichkeit, dies im Magento-Code zu tun, um die Wartbarkeit zu vereinfachen.
Es gibt einen interessanten Patch in diesem Thread: http://www.magentocommerce.com/boards/viewthread/31666/P0/ , der eine damit verbundene Deadlock-Bedingung zu lösen scheint (aber nicht diese speziell).
Edit: Anscheinend wurde Deadlocking bis zu einem gewissen Grad in CE 1.8 Alpha behoben. Suchen Sie noch nach einer Problemumgehung, bis diese Version von Alpha ist