Sto riscontrando un problema in cui ritengo che il processo di reindicizzazione del prezzo del prodotto stia causando un'eccezione di deadlock nel processo di pagamento.
Ho riscontrato questa eccezione nel processo di pagamento:
Eccezione di conversione ordine: SQLSTATE [40001]: errore di serializzazione: 1213 deadlock trovato durante il tentativo di ottenere il blocco; prova a riavviare la transazione
Sfortunatamente non ho una traccia dello stack completo a causa di dove è stata rilevata l'eccezione, ma controllando lo stato INNODB sono stato in grado di rintracciare il deadlock:
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`
Il blocco della tabella di richiesta SQL viene in definitiva generato da Mage_CatalogInventory_Model_Stock::registerProductsSale()
quando sta cercando di ottenere il conteggio corrente dell'inventario per ridurlo.
Al momento in cui si è verificato il deadlock, il processo di reindicizzazione del prezzo del prodotto era in esecuzione e suppongo che avesse un blocco di lettura sul catalog_product_entity table
che ha causato il deadlock. Se sto capendo correttamente il deadlock, qualsiasi blocco di lettura causerà un deadlock, ma il reindicizzazione del prezzo del prodotto mantiene il blocco per un tempo equo poiché il sito ha circa 50.000 prodotti.
Sfortunatamente, a questo punto nel flusso del codice di pagamento è stata addebitata la carta di credito del cliente (tramite un modulo di pagamento personalizzato) e la creazione dell'oggetto ordine corrispondente non è riuscita.
Le mie domande sono:
- La logica del modulo di pagamento personalizzato è difettosa? es. Esiste un flusso accettato per garantire che Magento possa convertire gratuitamente il preventivo in un'eccezione dell'ordine prima di impegnare l'addebito sul metodo di pagamento (carta di credito)?
Modifica: sembra che la logica del modulo di pagamento sia effettivamente difettosa poiché la chiamata a $ paymentmethod-> autorize () dovrebbe avvenire dopo il luogo in cui si verifica questo deadlock, non prima (come da risposta di Ivan in basso). Tuttavia, la transazione verrà comunque bloccata dal deadlock (anche se senza addebito errato sulla carta di credito).
Questa funzione chiama
$stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);
inMage_CatalogInventory_Model_Stock::registerProductsSale()
una lettura bloccata, quanto sarebbe pericoloso renderla una lettura non bloccante?Nella ricerca di una risposta sul Web, un paio di posizioni suggeriscono di non eseguire un reindicizzazione completa mentre il sito è caldo; difficilmente sembra una buona soluzione; il problema dell'indicizzazione che causa deadlock delle tabelle e blocco dei conflitti è un problema noto in Magento, ci sono soluzioni alternative?
Modifica: sembra che la domanda rimanente qui sia quella della terza domanda; reindicizzazione causando deadlock della tabella. Alla ricerca di soluzioni alternative per questo.
Modifica: il concetto che i deadlock non sono di per sé problemi, ma piuttosto la risposta a questi dovrebbe essere al centro, ha molto senso. Indagare ulteriormente per trovare un punto nel codice per rilevare l'eccezione di deadlock ed emettere nuovamente la richiesta. Fare questo a livello di adattatore DB Zend Framework è un approccio, ma sto anche cercando un modo per farlo nel codice Magento per facilitare la manutenibilità.
C'è una patch interessante in questo thread: http://www.magentocommerce.com/boards/viewthread/31666/P0/ che sembra risolvere una condizione di deadlock correlata (ma non questa in particolare).
Modifica: apparentemente il deadlock è stato indirizzato ad un grado in CE 1.8 Alpha. Sto ancora cercando una soluzione alternativa fino a quando questa versione non è uscita da Alpha