Estou com um problema em que acredito que o processo de re-indexação do preço do produto está causando uma exceção de impasse no processo de checkout.
Eu peguei essa exceção no processo de checkout:
Exceção de conversão de ordem: SQLSTATE [40001]: Falha de serialização: 1213 Impasse encontrado ao tentar obter o bloqueio; tente reiniciar a transação
Infelizmente, não tenho um rastreamento de pilha completo por causa de onde a exceção foi capturada, mas, ao verificar o status INNODB, consegui rastrear o 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`
O bloqueio da tabela solicitante do SQL é finalmente gerado a partir de Mage_CatalogInventory_Model_Stock::registerProductsSale()
quando ele tenta obter a contagem atual de inventário para diminuí-la.
No momento em que ocorreu o conflito, o processo de re-indexação do Preço do Produto estava em execução e eu suponho que ele tivesse um bloqueio de leitura no catalog_product_entity table
que causou o conflito. Se eu estiver entendendo o impasse corretamente, qualquer bloqueio de leitura causará um impasse, mas o re-índice de preços do produto mantém o bloqueio por um tempo razoável, pois o site possui ~ 50.000 produtos.
Infelizmente, nesse ponto do fluxo do código de pagamento, o cartão de crédito do cliente havia sido cobrado (por meio de um módulo de pagamento personalizado) e a criação do objeto de pedido correspondente falhou.
Minhas perguntas são:
- A lógica do módulo de pagamento personalizado está com defeito? ou seja, existe um fluxo aceito para garantir que o Magento possa converter a cotação em uma exceção de pedido sem antes de confirmar a cobrança no método de pagamento (cartão de crédito)?
Edit: Parece que a lógica do módulo de pagamento está realmente com defeito, pois a chamada para $ paymentmethod-> authorize () deve ocorrer após o local em que esse impasse ocorre, não antes (conforme a resposta de Ivan abaixo). No entanto, a transação ainda será bloqueada pelo impasse (embora sem a cobrança incorreta no cartão de crédito).
Esta chamada de função
$stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);
emMage_CatalogInventory_Model_Stock::registerProductsSale()
torna uma leitura de bloqueio, o quão perigoso seria para torná-lo uma leitura sem bloqueio?Ao pesquisar na Web por uma resposta, alguns lugares sugeriram não executar uma nova indexação completa enquanto o site estiver quente; dificilmente parece uma boa solução; é a questão da indexação causando conflitos de tabela e contenção de bloqueios um problema conhecido no Magento, existem soluções alternativas?
Edit: Parece que a questão restante aqui é a da terceira questão; re-indexação causando deadlocks na tabela. Procurando soluções alternativas para isso.
Edit: O conceito de que os impasses não são, por si só, problemas, mas a resposta a eles deve ser o foco, faz muito sentido. Investigue mais para encontrar um ponto no código para capturar a exceção de conflito e reemitir a solicitação. Fazer isso no nível do adaptador Zend Framework DB é uma abordagem, mas também estou procurando uma maneira de fazer isso no código Magento para facilitar a manutenção.
Há um patch interessante neste segmento: http://www.magentocommerce.com/boards/viewthread/31666/P0/ que parece resolver uma condição de conflito relacionada (mas não esta especificamente).
Edit: Aparentemente, o impasse foi endereçado a um grau no CE 1.8 Alpha. Ainda estou procurando uma solução alternativa até que esta versão esteja fora do Alpha