Estoy experimentando un problema en el que creo que el proceso de reindexación del precio del producto está causando una excepción de punto muerto en el proceso de pago.
Capté esta excepción en el proceso de pago:
Excepción de conversión de orden: SQLSTATE [40001]: error de serialización: 1213 Punto muerto encontrado al intentar bloquear; intente reiniciar la transacción
Desafortunadamente, no tengo un seguimiento completo de la pila debido a dónde se detectó la excepción, pero al verificar el estado de INNODB pude rastrear el punto muerto:
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`
El bloqueo de la tabla de solicitud de SQL se genera en última instancia Mage_CatalogInventory_Model_Stock::registerProductsSale()
cuando se intenta obtener el recuento de inventario actual para disminuirlo.
En el momento en que se produjo el punto muerto, el proceso de reindexación del precio del producto se estaba ejecutando y supongo que tenía un bloqueo de lectura catalog_product_entity table
que causó el punto muerto. Si entiendo el punto muerto correctamente, cualquier bloqueo de lectura provocará un punto muerto, pero el re-índice del precio del producto mantiene el bloqueo durante un tiempo justo ya que el sitio tiene ~ 50,000 productos.
Desafortunadamente, en este punto del flujo del código de pago, la tarjeta de crédito del cliente había sido cargada (a través de un módulo de pago personalizado) y la creación del objeto de pedido correspondiente falló.
Mis preguntas son:
- ¿La lógica del módulo de pago personalizado es defectuosa? es decir, ¿hay un flujo aceptado para garantizar que Magento pueda convertir la cotización a una orden de excepción gratis antes de comprometer el cargo al método de pago (tarjeta de crédito)?
Editar: Parece que la lógica del módulo de pago es realmente defectuosa ya que la llamada a $ paymentmethod-> authorize () debería ocurrir después del lugar donde se produce este punto muerto, no antes (según la respuesta de Ivan a continuación). Sin embargo, la transacción seguirá siendo bloqueada por el punto muerto (aunque sin el cargo erróneo a la tarjeta de crédito).
Esta llamada a la función
$stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);
enMage_CatalogInventory_Model_Stock::registerProductsSale()
la convierte en una lectura de bloqueo, lo peligroso que sería para que sea una lectura sin bloqueo?Al buscar en la web una respuesta, un par de lugares sugirieron no ejecutar una reindexación completa mientras el sitio está activo; difícilmente parece una buena solución; ¿Es el problema de la indexación que causa puntos muertos de tabla y contención de bloqueo un problema conocido en Magento? ¿Hay soluciones alternativas?
Editar: Parece que la pregunta restante aquí es la de la tercera pregunta; reindexar causando puntos muertos en la tabla. Buscando soluciones para esto.
Editar: el concepto de que los puntos muertos no están en sí mismos, sino que la respuesta a ellos debería ser el foco, tiene mucho sentido. Investigando más a fondo para encontrar un punto en el código para detectar la excepción de punto muerto y volver a emitir la solicitud. Hacer esto en el nivel del adaptador Zend Framework DB es un enfoque, pero también estoy buscando una manera de hacerlo en el código de Magento para facilitar el mantenimiento.
Hay un parche interesante en este hilo: http://www.magentocommerce.com/boards/viewthread/31666/P0/ que parece resolver una condición de punto muerto relacionada (pero no esta específicamente).
Editar: Aparentemente, el punto muerto se ha abordado hasta cierto punto en CE 1.8 Alpha. Todavía estoy buscando una solución hasta que esta versión esté fuera de Alpha