चेकआउट के दौरान डीबी गतिरोध के कारण मूल्य पुन: सूचकांक


47

मैं एक समस्या का सामना कर रहा हूं, जहां मेरा मानना ​​है कि उत्पाद मूल्य पुन: अनुक्रमण प्रक्रिया चेकआउट प्रक्रिया में एक गतिरोध अपवाद का कारण बन रही है।

मैंने चेकआउट प्रक्रिया में इस अपवाद को पकड़ा:

आदेश रूपांतरण अपवाद: SQLSTATE [40001]: सीरियलाइज़ेशन विफलता: 1213 गतिरोध पाया गया जब ताला पाने की कोशिश कर रहा था; लेनदेन को पुनः आरंभ करने का प्रयास करें

दुर्भाग्य से मेरे पास पूर्ण स्टैक ट्रेस नहीं है क्योंकि अपवाद को पकड़ा गया था, लेकिन INNODB स्थिति की जांच करने से मैं गतिरोध को ट्रैक करने में सक्षम था:

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` 

SQL अनुरोध तालिका लॉक अंततः से उत्पन्न होता है Mage_CatalogInventory_Model_Stock::registerProductsSale()जब यह वर्तमान इन्वेंट्री गणना प्राप्त करने की कोशिश कर रहा है ताकि इसे घटाया जा सके।

जिस समय गतिरोध हुआ, उस समय उत्पाद मूल्य पुन: अनुक्रमणिका प्रक्रिया चल रही थी और मैं यह मान रहा था कि catalog_product_entity tableइस गतिरोध के कारण रीड लॉक था । यदि मैं गतिरोध को सही ढंग से समझ रहा हूं तो कोई भी पढ़ा हुआ लॉक गतिरोध पैदा कर सकता है, लेकिन उत्पाद की कीमत फिर से बंद हो जाती है, क्योंकि साइट में 50,000 उत्पाद हैं।

दुर्भाग्य से, चेकआउट कोड के प्रवाह में ग्राहक के क्रेडिट कार्ड से (कस्टम भुगतान मॉड्यूल के माध्यम से) शुल्क लिया गया था, और संबंधित ऑर्डर ऑब्जेक्ट का निर्माण विफल हो गया।

मेरे प्रश्न हैं:

  • क्या कस्टम भुगतान मॉड्यूल तर्क दोषपूर्ण है? यानी क्या यह सुनिश्चित करने के लिए एक स्वीकृत प्रवाह है कि भुगतान विधि (क्रेडिट) को चार्ज करने से पहले Magento एक ऑर्डर अपवाद को उद्धरण मुक्त कर सकता है?

संपादित करें: ऐसा प्रतीत होता है कि भुगतान मॉड्यूल तर्क वास्तव में दोषपूर्ण है क्योंकि $ paymethod-> को प्राधिकृत करना () उस स्थान के बाद होना चाहिए जहां यह गतिरोध होता है, इससे पहले नहीं (नीचे के इवान के जवाब के अनुसार)। हालाँकि, लेन-देन अभी भी गतिरोध (क्रेडिट कार्ड के लिए गलत शुल्क के बिना) द्वारा अवरुद्ध किया जाएगा।

  • इस समारोह कॉल $stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);में Mage_CatalogInventory_Model_Stock::registerProductsSale()बनाता है यह एक ताला पढ़ने, कितना खतरनाक हो सकता है यह एक गैर ताला लगा पढ़ने बनाने के लिए?

  • एक उत्तर के लिए वेब पर खोज करने के लिए कुछ स्थानों पर सुझाव दिया गया है कि साइट के गर्म होने पर पूर्ण पुन: अनुक्रमण नहीं किया जाएगा; शायद ही एक अच्छा समाधान की तरह लगता है; क्या मैगेंटो में टेबल डेडलॉक और लॉक कॉन्टैक्शन को एक ज्ञात मुद्दा बनाने के लिए इंडेक्सिंग का मुद्दा है, क्या वर्कअराउंड हैं?

संपादित करें: ऐसा लगता है कि शेष प्रश्न यहां तीसरे प्रश्न से एक है; तालिका गतिरोध के कारण पुन: अनुक्रमण। इसके लिए वर्कअराउंड की तलाश कर रहे हैं।

संपादित करें: गतिरोध जो अवधारणा स्वयं के मुद्दों में नहीं है, बल्कि उन पर प्रतिक्रिया फोकस होना चाहिए, बहुत समझ में आता है। गतिरोध अपवाद को पकड़ने के लिए कोड में एक बिंदु खोजने और अनुरोध को फिर से जारी करने के लिए आगे की जांच। ज़ेंड फ्रेमवर्क डीबी एडेप्टर स्तर पर ऐसा करना एक दृष्टिकोण है, लेकिन रखरखाव को आसान बनाने के लिए मैगेंटो कोड में ऐसा करने का एक तरीका भी ढूंढ रहा है।

इस धागे में एक दिलचस्प पैच है: http://www.magentocommerce.com/boards/viewthread/31666/P0/ जो संबंधित गतिरोध की स्थिति को हल करने के लिए लगता है (लेकिन यह विशेष रूप से नहीं)।

संपादित करें: जाहिरा तौर पर गतिरोध को सीई 1.8 अल्फा में एक डिग्री तक संबोधित किया गया है। अभी भी वर्कअराउंड की तलाश है जब तक कि यह संस्करण अल्फा से बाहर न हो


हम हाल ही में इसी तरह की समस्या से जूझ रहे हैं, आप किस भुगतान विस्तार का उपयोग कर रहे हैं?
पीटर ओ'कालाघन

यह एक कस्टम कोडित एक्सटेंशन है
Roscius

1
@kalenjordan 1.13 में अनुक्रमण सुधार और फिलिंकल के नीचे की तरह पुन: प्रयास योजना ने बड़े पैमाने पर मेरे लिए समस्या को कम कर दिया है।
रोज़ीस

1
@ रोसियस लगभग कितना उन्होंने इसे कम किया है? मैं किसी प्रकार की DB विफलताओं को देख रहा हूं (कनेक्शन टाइमआउट, लॉक वेट टाइमआउट, गतिरोध) मेरे आदेशों का लगभग 0.2% प्रभावित करता है। बहुत दुर्लभ लेकिन मैं वास्तव में इसे पूरी तरह से हल करना चाहता हूं।
कलनजोड़न

जवाबों:


16

इस बात की काफी संभावना है कि आपका भुगतान तरीका गलत तरीके से भुगतान को संसाधित कर रहा है।

Magento ऑर्डर सेव प्रोसेस काफी सरल है:

  • कीमतों और उत्पाद की जानकारी सहित सभी डेटा को कोट आइटम से ऑर्डर आइटम में स्थानांतरित किया जाना चाहिए, बाद में यह मूल्य पुनर्प्राप्ति को लागू नहीं करता है।
  • आदेश सबमिट करने से पहले ईवेंट सबमिट करें checkout_type_onepage_save_orderऔरsales_model_service_quote_submit_before
    • Mage_CatalogInventory_Model_Stock::registerProductsSale() इस घटना पर्यवेक्षक पर लागू किया गया है
  • DB लेनदेन शुरू करें
  • आह्वान $order->place()विधि जो कॉल करके भुगतान की प्रक्रिया करती है $paymentMethod->authorize(), $paymentMethod->capture()या $paymentMethod->initialize()उसके तर्क पर निर्भर करती है।
  • $ ऑर्डर-> सहेजें () विधि को संसाधित करें जो प्रोबेड ऑर्डर को डीबी टेबल में बचाता है sales_flat_order_*
  • प्रतिबद्ध डीबी लेनदेन (इस चरण पर डीबी इन्वेंट्री टेबल पर लॉक जारी करता है)

इसलिए जैसा कि आप देखते हैं, यह संभव नहीं हो सकता है, कि भुगतान पद्धति इन्वेंट्री लॉक से पहले पैसे वसूलती है और उत्पाद की कीमतों या उत्पाद की जानकारी पढ़ती है।

यह तभी संभव है जब भुगतान विधि को इस तरह से लागू किया जाता है, कि चार्जिंग ऑपरेशन के लिए एपीआई कॉल करने के बाद यह कीमतों के साथ उत्पादों की लोडिंग स्वयं करता है।

आशा है कि यह आपकी समस्या को डीबग करने में आपकी मदद करेगा।

यदि आप भुगतान विधि के साथ यह समस्या नहीं रखते हैं, तो यह सुरक्षित रखने के लिए, यह सुरक्षित होना चाहिए। चूँकि पैसे से चार्ज होने से पहले रीड ऑपरेशन जो तालों पर निर्भर होता है।


1
धन्यवाद, ऐसा लगता है कि कस्टम भुगतान मॉड्यूल तर्क थोड़ा बंद है। हालांकि यह अभी भी दिखता है कि एक अनुक्रमण प्रक्रिया चेकआउट को रोक देगी, जिसमें एक अपवाद पैदा होता है registerProductsSale()(यह समझकर कि कस्टम भुगतान मॉड्यूल में सुधार के साथ ग्राहक के कार्ड चार्ज होने की समस्या को दूर किया जाएगा)।
रोजिअस

8

क्योंकि यह एक कस्टम एक्सटेंशन है, हम कोर फाइलों को एडिट किए बिना सेव को रिट्रीट करने के लिए एक कस्टम वर्कअराउंड (पढ़ें: हैक) पा सकते हैं।

मैंने अपने सभी गतिरोधों को हल किया है, निम्न दो तरीकों से एक सहायक वर्ग में जोड़ा गया है। $product->save()मैं अब कॉल करने के बजाय कॉल करता हूं Mage::helper('mymodule')->saferSave($product):

/**
 * Save with a queued retry upon deadlock, set isolation level
 * @param  stdClass $obj object must have a pre-defined save() method
 * @return n/a      
 */
public function saferSave($obj)
{

    // Deadlock Workaround
    $adapter = Mage::getModel('core/resource')->getConnection('core_write');
    // Commit any existing transactions (use with caution!)
    if ($adapter->getTransactionLevel > 0) {
        $adapter->commit();
    }
    $adapter->query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');

    //begin a retry loop that will recycle should a deadlock pop up
    $tries = 0;
        do {
            $retry = false;
            try {
                $obj->save();
            } catch (Exception $e) {
                if ($tries < 10 and $e->getMessage()=='SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction') {
                    $retry = true;
                } else {
                    //we tried at least 10 times, go ahead and throw exception
                    throw new Zend_Db_Statement_Exception($e->getMessage());
                }
                sleep($this->getDelay());
                $tries++;
            }
        } while ($retry);

    //free resources
    unset($adapter);
    return;
}

public function getDelay($tries){
    return (int) pow(2, $tries);
}

यह दो अलग-अलग चीजों को पूरा करता है - यह एक गतिरोध का सामना करने पर पुन: प्रयास करता है और यह उस रिट्री के लिए तेजी से बढ़ते समय निर्धारित करता है। यह लेन-देन अलगाव स्तर भी निर्धारित करता है। MySQL के लेनदेन अलगाव स्तरों के बारे में अधिक जानकारी के लिए SO और DBA.SE पर बहुत सारी जानकारी है।

एफडब्ल्यूआईडब्ल्यू, मैंने तब से गतिरोध का सामना नहीं किया है।


1
@Mage :: getModel ('कोर / संसाधन') @ को एक नया कनेक्शन बनाना चाहिए। मुझे समझ में नहीं आता है कि यह मौजूदा लेनदेन अलगाव स्तर को कैसे बदल सकता है।
11

@giftnuss मेला काफी सुनिश्चित करने के लिए सिंगलटन होना चाहिए।
Github

@ मैन इस आदमी के लिए धन्यवाद। मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या ईई 1.13 अपग्रेड मेरे संकटों को हल करेगा या मुझे इस पर भी ध्यान देना चाहिए। मुझे पता है कि 1.13 अतुल्यकालिक रूप से अनुक्रमण करता है जो महान है लेकिन यदि वही अंतर्निहित प्रश्न शामिल हैं, तो मुझे यह समझने में एक कठिन समय है कि कैसे async अकेले डेडलॉक को कभी भी होने से रोकेगा।
कालेंजर्डन

1
@kalenjordan यह async और 1.8 / 1.13 में अद्यतन varien db परिवर्तनों का एक संयोजन है जो गतिरोध की संभावना को कम करता है।
९'१४ को

मुझे लगता है कि आप $triesइस समारोह में जाना भूल गएsleep($this->getDelay());
ताहिर यासीन

3

Magento के मंचों पर वे एक Zend पुस्तकालय फ़ाइल को संपादित करने के बारे में बात करते हैं: lib / Zend / Db / कथन / Pdo.php

मूल _execute फ़ंक्शन:

public function _execute(array $params = null)
    {
        // begin changes
        $tries = 0;
        do {
            $retry = false;
            try {
                if ($params !== null) {
                    return $this->_stmt->execute($params);
                } else {
                    return $this->_stmt->execute();
                }
            } catch (PDOException $e) {
                #require_once 'Zend/Db/Statement/Exception.php';
                if ($tries < 10 and $e->getMessage()=='SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction') {
                    $retry = true;
                } else {
                    throw new Zend_Db_Statement_Exception($e->getMessage());
                }
                $tries++;
            }
        } while ($retry);
        // end changes
    }

संशोधन के बाद:

public function _execute(array $params = null)
    {
        $tries = 0;
        do {
            $retry = false;
            try {
                $this->clear_result();
                $result = $this->getConnection()->query($sql);
                $this->clear_result();
            }
            catch (Exception $e) {
                if ($tries < 10 and $e->getMessage()=='SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction') {
                    $retry = true;
                } else {
                    throw $e;
                }
                $tries++;
            }
        } while ($retry);

        return $result;
    }

जैसा कि आप केवल एक चीज देख सकते हैं जिसे बदल दिया गया है वह यह है कि $ कोशिशों को लूप के बाहर ले जाया गया है।

हमेशा यह सुझाव दिया जाता है कि इसे एक विकास / परीक्षण वातावरण पर आज़माएं और उत्पादन वातावरण पर इस फ़िक्स को तुरंत लागू न करें।


2
मुझे अंतर्निहित फ्रेमवर्क फ़ाइलों को संपादित करने के बारे में चिंता है, ऐसा लगता है कि इसके बजाय मैगेंटो कोड स्तर पर पुनर्प्रयास होना चाहिए।
रोजिअस

हमने सुझाए गए फिक्स की कोशिश की है, और इसने वास्तव में इस विशेष गतिरोध को मुद्दों को पैदा करने से रोका है। हमें सेल्स_फ्लैट_ऑर्डर_ग्रिड पर सेव पर डेडलॉक भी प्राप्त हो रहे थे, इस फिक्स जगह के साथ, वे इसके बजाय अखंडता उल्लंघन उल्लंघन करते हैं, जो स्पष्ट रूप से अच्छा नहीं है।
पीटर ओ'कालाघन

2

मैं एक Magento 1.11 साइट पर यह एक ही मुद्दा है और मैं 11/12/2012 के बाद से Magento के साथ एक खुला टिकट है। उन्होंने पुष्टि की कि यह एक मुद्दा है और लगता है कि एक पैच बनाया जाएगा।

मेरा सवाल यह है कि इस समय कीमत क्यों है? मुझे नहीं लगता कि इसकी आवश्यकता है:

#8 /var/www/html/app/code/core/Mage/CatalogInventory/Model/Observer.php(689): Mage_Catalog_Model_Resource_Product_Indexer_Price->reindexProductIds(Array)

1
यदि कोई उत्पाद स्टॉक से बाहर हो जाता है और स्टॉक उत्पादों से बाहर कैटलॉग में प्रदर्शित नहीं किया जाता है, तो मेरा मानना ​​है कि वे कोई मूल्य सूचकांक रिकॉर्ड रखने की योग्यता से छिपे हुए हैं, जो मूल्य संग्रह में शामिल होने पर उन्हें उत्पाद संग्रह से बाहर कर देते हैं। ।
davidalger

इस सवाल का जवाब नहीं है। ऐसा लगता है कि आप मूल प्रश्न में अतिरिक्त जानकारी जोड़ने का प्रयास कर रहे हैं। शायद यह जानकारी मूल प्रश्न पर टिप्पणी के रूप में बेहतर होगी।
ल्यूक मिल्स

मैं तुम्हारे साथ हूँ, किम। मैंने 11/2011 से एक ही टिकट खोला है।
फिल्हाल

मुझे पता है कि यह तकनीकी रूप से एक उत्तर नहीं बल्कि एक उप-प्रश्न है, हालांकि यह इस प्रश्न का उत्तर देता है जो इस प्रश्न को एक डुप्लिकेट के रूप में संदर्भित करता है! तो किम्बर्ली थॉमस और डेविएल्गर को मेरे विशिष्ट "मेरे लिए यह क्यों है?" सवाल है कि मैं वर्तमान में कर रहा हूँ; धन्यवाद!
सिग्नस डिजिटल

0

हमारे पास एक ऐसा ही गतिरोध मुद्दा था जब एक पुन: सूचकांक के दौरान कुछ कॉल किए गए थे। हमारे लिए यह स्वयं ही प्रकट होता है जब कोई ग्राहक कार्ट में कुछ जोड़ रहा होता है। संभवत: वास्तविक अंतर्निहित समस्या को ठीक नहीं करते हुए, अतुल्यकालिक पुन: अनुक्रमण को लागू करना उन सभी गतिरोध कॉलों को पूरी तरह से रोक दिया है जिन्हें हम पहले देख रहे थे। अंतर्निहित समस्या तय होने तक स्टॉप-गैप के रूप में काम करना चाहिए और ईई / सीई संस्करणों में धकेल दिया जाना चाहिए (हमने ऐसा करने के लिए एक एक्सटेंशन की खरीद समाप्त कर दी)।


0

मेरा सुझाव है कि आप Philwinkle DeadlockRetry स्थापित करें। इसने हमारे डेटाबेस के लिए काम किया।

https://github.com/philwinkle/Philwinkle_DeadlockRetry

मैं यह भी सुझाव देना चाहूंगा कि आपके किसी भी बाहरी कार्यक्रम को अपने वेब एप पर हिट करते हुए देखें। हमारे पास एक था जो उत्पादों के लिए मात्रा को अपडेट कर रहा था और यह कई गतिरोध पैदा कर रहा था। हमने फिर से लिखा और डेटाबेस में सीधे चला गया।


1
यह रेपो अब समर्थित नहीं है, लेकिन सौभाग्य से यह प्रतिस्थापन github.com/AOEpeople/Aoe_DbRetry की सिफारिश करता है ।
हंस

-1

मैं पिछले साल कई बार गतिरोध के मुद्दे पर मिला, मैंने इसे केवल अपने सर्वर के लिए मेमोरी बढ़ाकर हल किया क्योंकि अनुक्रमण प्रक्रिया सभी संसाधनों को खाती है।

तुम भी हमें async reindex समाधान मैं चमत्कार इस्तेमाल किया जाना चाहिए

अधिक स्थिर प्रणाली के लिए, आपको अपने बैकएंड को फ्रंटएंड से अलग करने के बारे में सोचना चाहिए ताकि वे एक-दूसरे की रैम न खाएं।

मेरे अनुभव के लिए, यह स्रोत कोड की समस्या नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.