মূল্য পুনরায় সূচক চেকআউট চলাকালীন ডিবি অচলাবস্থা সৃষ্টি করে


47

আমি এমন একটি সমস্যার মুখোমুখি হয়েছি যেখানে আমি বিশ্বাস করি যে পণ্যের মূল্য পুনরায় সূচি প্রক্রিয়া চেকআউট প্রক্রিয়াটিতে একটি অচলাবস্থা ব্যতিক্রম ঘটায়।

আমি চেকআউট প্রক্রিয়াতে এই ব্যতিক্রমটি ধরলাম:

অর্ডার রূপান্তর ব্যতিক্রম: এসকিউএলস্টেট [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` 

এসকিউএল অনুরোধের টেবিল লকটি চূড়ান্তভাবে তৈরি করা হয় Mage_CatalogInventory_Model_Stock::registerProductsSale()যখন এটি হ্রাস করার জন্য বর্তমান ইনভেন্টরি গণনা পাওয়ার চেষ্টা করছে।

অচলাবস্থার সময়, পণ্যের মূল্য পুনরায় সূচী প্রক্রিয়া চলছিল এবং আমি ধরে নিচ্ছি যে এটিতে একটি রিড লক রয়েছে catalog_product_entity tableযার ফলে অচলাবস্থার সৃষ্টি হয়েছিল। আমি যদি অচলতটি সঠিকভাবে বুঝতে পারি তবে যে কোনও পঠিত লক একটি অচলাবস্থার কারণ হয়ে উঠবে, তবে পণ্যের মূল্য পুনরায় সূচীটি তালিকার জন্য উপযুক্ত সময়ের জন্য লকটি ধরে রাখে কারণ সাইটের ~ 50,000 পণ্য রয়েছে।

দুর্ভাগ্যক্রমে, চেকআউট কোড প্রবাহের এই সময়ে গ্রাহকের ক্রেডিট কার্ড চার্জ করা হয়েছিল (কাস্টম পেমেন্ট মডিউলটির মাধ্যমে), এবং সম্পর্কিত অর্ডার অবজেক্ট তৈরি করা ব্যর্থ হয়েছিল।

আমার প্রশ্নগুলি হ'ল:

  • কাস্টম পেমেন্ট মডিউল লজিক ত্রুটিযুক্ত? অর্থাত্ পেমেন্ট পদ্ধতিতে (ক্রেডিট কার্ড) চার্জ দেওয়ার আগে ম্যাজেন্টো উক্ত উদ্ধৃতিটিকে একটি অর্ডার ব্যয়ে ফ্রি রূপান্তর করতে পারে তা নিশ্চিত করার জন্য কি কোনও গ্রহণযোগ্য প্রবাহ রয়েছে?

সম্পাদনা: এটি প্রদর্শিত হচ্ছে পেমেন্ট মডিউল যুক্তিটি সত্যই ত্রুটিযুক্ত কারণ dead পেমেন্টমেডোথড>> অনুমোদন () এ কল করার পরে যেখানে এই অচলাবস্থা ঘটেছিল তার আগে ঘটবে, আগে নয় (ইভানের উত্তর অনুসারে)। তবে লেনদেনটি এখনও অচলাবস্থার দ্বারা অবরুদ্ধ থাকবে (ক্রেডিট কার্ডের ত্রুটিযুক্ত চার্জ ব্যতীত)।

  • এই ফাংশনটি কল $stockInfo = $this->_getResource()->getProductsStock($this, array_keys($qtys), true);মধ্যে Mage_CatalogInventory_Model_Stock::registerProductsSale()তোলে এটি একটি লকিং পঠিত, কতটা বিপজ্জনক এটি হবে এটি একটি অ-লক পঠিত করতে?

  • উত্তরের জন্য ওয়েব অনুসন্ধান করতে গিয়ে বেশ কয়েকটি জায়গার পরামর্শ দেওয়া হয়েছিল যে সাইটটি গরম থাকাকালীন সম্পূর্ণ পুনরায় সূচীকরণ না চালাবে; একটি ভাল সমাধান খুব কমই মনে হয়; টেস্টের অচলাবস্থা এবং লক বিতর্ককে ইন্ডেক্স করার বিষয়টি কি ম্যাজেন্টোতে একটি জ্ঞাত সমস্যা, সেখানে কি কর্মক্ষেত্র রয়েছে?

সম্পাদনা: মনে হচ্ছে এখানে অবশিষ্ট প্রশ্নটি তৃতীয় প্রশ্ন থেকে এক; পুনরায় সূচীকরণের ফলে টেবিলের অচলাবস্থা রয়েছে। এর জন্য কাজের সন্ধান করছি।

সম্পাদনা করুন: যে ধারণাটি অচলাবস্থাগুলি অন্তর্ভুক্ত নয় এবং সেগুলি নিজেরাই ইস্যু করে না, বরং তাদের প্রতিক্রিয়াটি ফোকাস হওয়া উচিত, তা অনেকটা বোঝায়। অচলাবস্থা ব্যতিক্রম ধরা এবং অনুরোধটি পুনরায় প্রকাশ করার জন্য কোডের একটি বিন্দু খুঁজে পেতে আরও তদন্ত করা হচ্ছে। জেন্ড ফ্রেমওয়ার্ক ডিবি অ্যাডাপ্টারের স্তরে এটি করা একটি পদ্ধতির, তবে রক্ষণাবেক্ষণযোগ্যতা স্বাচ্ছন্দ্যের জন্য ম্যাজেন্টো কোডে এটি করার একটি উপায়ও খুঁজছি।

এই থ্রেডে একটি আকর্ষণীয় প্যাচ রয়েছে: http://www.magentocommerce.com/boards/viewthread/31666/P0/ যা সম্পর্কিত অচলাবস্থার শর্তটি সমাধান করে বলে মনে হচ্ছে (তবে এটি বিশেষত এটি নয়)।

সম্পাদনা করুন: স্পষ্টতই ডেডলকিং সিই 1.8 সালে একটি ডিগ্রীতে সম্বোধন করা হয়েছে আলফা। এই সংস্করণটি আলফা থেকে বের না হওয়া অবধি এখনও একপর্যায়ে খুঁজছেন


আমরা সম্প্রতি একই ধরণের সমস্যার সাথে লড়াই করছি, আপনি কোন পেমেন্ট এক্সটেনশন ব্যবহার করছেন?
পিটার ও'ক্যালাহান

এটি একটি কাস্টম কোডড এক্সটেনশন
রোসিউইস

1
@ ক্যালেনজর্ডান ১.১৩-তে সূচীকরণের অনুক্রমসমূহ এবং নীচে ফিলুইঙ্কলের মতো পুনরায় চেষ্টা করার প্রকল্পটি আমার জন্য বিষয়টি বেশিরভাগ ক্ষেত্রে প্রশমিত করেছে।
রোসিউইস

1
@ রসসিয়াস প্রায় তারা কতটা প্রশমিত করেছেন? আমি কোনও ধরণের ডিবি ব্যর্থতা দেখতে পাচ্ছি (সংযোগের সময়সীমা, লক ওয়েট টাইমআউট, ডেডলক) আমার অর্ডারগুলির প্রায় 0.2% প্রভাবিত করে। খুব বিরল তবে আমি সত্যিই এটি সম্পূর্ণরূপে সমাধান করতে চাই।
কালেঞ্জর্ডান

উত্তর:


16

আপনার অর্থ প্রদানের পদ্ধতিটি ভুলভাবে অর্থ প্রদানের প্রক্রিয়া করছে এমন যথেষ্ট সম্ভাবনা রয়েছে।

ম্যাজেন্টো অর্ডার সেভ প্রক্রিয়াটি বেশ সহজ:

  • মূল্য এবং পণ্য সম্পর্কিত তথ্য সহ কোট আইটেম থেকে অর্ডার আইটেমে স্থানান্তরিত হওয়া উচিত এমন সমস্ত ডেটা প্রস্তুত করে, এরপরে এটি দাম পুনরুদ্ধারের অনুরোধ করে না।
  • অর্ডার ইভেন্ট জমা দেওয়ার আগে আমন্ত্রণ করুন checkout_type_onepage_save_orderএবংsales_model_service_quote_submit_before
    • Mage_CatalogInventory_Model_Stock::registerProductsSale() এই ইভেন্ট পর্যবেক্ষককে অনুরোধ করা হয়েছে
  • ডিবি লেনদেন শুরু করুন
  • ডাকা $order->place()পদ্ধতি যা কল করে পেমেন্ট প্রক্রিয়া $paymentMethod->authorize(), $paymentMethod->capture()বা $paymentMethod->initialize()তার যুক্তিবিজ্ঞান উপর নির্ভর করে।
  • Vo অর্ডার-> সংরক্ষণ করুন () পদ্ধতিটি ডিবি টেবিলগুলিতে প্রক্রিয়াজাত অর্ডার সংরক্ষণ করে 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);
}

এটি দুটি স্বতন্ত্র জিনিস সম্পাদন করে - কোনও অচলাবস্থার মুখোমুখি হওয়ার সাথে সাথে এটি পুনরায় চেষ্টা করার জন্য সারি তৈরি করে এবং এটি পুনরায় চেষ্টা করার জন্য দ্রুত বৃদ্ধি করার সময়সীমা নির্ধারণ করে। এটি লেনদেনের বিচ্ছিন্নতা স্তরও নির্ধারণ করে। মাইএসকিউএল এর লেনদেন বিচ্ছিন্নতা স্তর সম্পর্কে আরও তথ্যের জন্য এসও এবং ডিবিএ.এসইতে প্রচুর তথ্য রয়েছে।

এফডাব্লুআইডাব্লু, এর পর থেকে আমি কোনও অচলাবস্থার মুখোমুখি হই নি।


1
@ ম্যাজ :: গেটমোডেল ('কোর / রিসোর্স') @ এর একটি নতুন সংযোগ তৈরি করা উচিত। আমি বুঝতে পারি না এটি কীভাবে বর্তমান লেনদেনের বিচ্ছিন্নতা স্তর পরিবর্তন করতে পারে।
গিফটনস

@ giftnuss মেলা যথেষ্ট। নিশ্চিতভাবে একক হতে হবে।
গিথুব

এই ব্যক্তির জন্য ধন্যবাদ আমি EE 1.13 আপগ্রেড আমার সমস্যাগুলি সমাধান করবে কিনা তাও চেষ্টা করার চেষ্টা করছি বা আমারও এটির দিকে নজর দেওয়া উচিত। আমি জানি যে 1.13 অ্যাসিক্রোনালিকভাবে সূচক তৈরি করে যা দুর্দান্ত but
কালেঞ্জর্ডান

1
@ ক্যালেনজর্ডান এটি অ্যাসিঙ্কের সংমিশ্রণ এবং 1.8 / 1.13 এ আপডেট হওয়া ভেরিয়েন ডিবি পরিবর্তনের ফলে ডেডলকের সম্ভাবনা হ্রাস পায়।
ফিলিউঙ্কল

আমি মনে করি আপনি $triesএই অনুষ্ঠানে যেতে ভুলে গেছেনsleep($this->getDelay());
তাহির ইয়াসিন

3

ম্যাজেন্টো ফোরামে তারা জেন্ড লাইব্রেরি ফাইল সম্পাদনা করার বিষয়ে কথা বলেন: lib / Zend / Db / Statement / Pdo.php

আসল _ এক্সিকিউট ফাংশন:

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

আমার একই সমস্যাটি ম্যাজেন্টো 1.11 সাইটে রয়েছে এবং 11/12/2012 থেকে আমার এতে ম্যাজেন্টোর সাথে একটি উন্মুক্ত টিকিট আছে। তারা নিশ্চিত করেছে যে এটি একটি সমস্যা এবং মনে করা হয় তারা কোনও প্যাচ তৈরি করছে।

আমার প্রশ্ন হ'ল এই সময়ে দামটি কেন পুনরায় মূল্যায়ন করতে হবে? আমি মনে করি না এটি প্রয়োজন:

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

1
যদি কোনও পণ্য স্টকের বাইরে চলে যায় এবং স্টক পণ্যগুলির বাইরে ক্যাটালগটিতে প্রদর্শিত না হয়, তবে আমি বিশ্বাস করি যে মূল্য নির্ধারণের সাথে যুক্ত হওয়ার পরে পণ্য সংগ্রহ থেকে বাদ দিয়ে শেষ করে কোনও মূল্য সূচক রেকর্ড না রেখে যোগ্যতার দ্বারা তারা লুকিয়ে থাকে believe ।
ডেভিডালগার

এটি প্রশ্নের উত্তর দেয় না। দেখে মনে হচ্ছে আপনি মূল প্রশ্নে অতিরিক্ত তথ্য যুক্ত করার চেষ্টা করছেন। মূল প্রশ্নটিতে মন্তব্য হিসাবে সম্ভবত এই তথ্যটি আরও ভাল হবে।
লুক মিলস

আমি তোমার সাথে আছি, কিম। 11/2011 থেকে আমার একই টিকিট খোলা আছে।
ফিলিভিঙ্কল

আমি জানি এটি প্রযুক্তিগতভাবে কোনও উত্তর নয় বরং একটি উপ-প্রশ্ন, তবে এটি এই প্রশ্নের উত্তর দেয় যা এই প্রশ্নটিকে সদৃশ হিসাবে উল্লেখ করে! সুতরাং কিম্বারলি থমাস এবং ডেভিডালগার আমার নির্দিষ্ট উত্তর দেওয়ার জন্য আমার উত্সাহ পেতে "এটি কেন মূল্য পুনর্নির্মাণ?" আমি যে প্রশ্ন করছি এখন; ধন্যবাদ!
সিগনাস ডিজিটাল

0

পুনরায় সূচকের সময় নির্দিষ্ট কল করা হয়েছিল তখন আমাদের একই রকমের অচলাবস্থার সমস্যা ছিল। আমাদের জন্য এটি বেশিরভাগ ক্ষেত্রেই প্রকাশ পায় যখন কোনও গ্রাহক কার্টে কিছু যুক্ত করে। সম্ভবত প্রকৃত অন্তর্নিহিত সমস্যাটি ঠিক না করার সময়, অ্যাসিক্রোনাস পুনরায় সূচি বাস্তবায়ন করা আমরা পূর্বে যে সমস্ত ডেডলক কলগুলি দেখছিলাম তা সম্পূর্ণভাবে বন্ধ করে দিয়েছে। অন্তর্নিহিত সমস্যাটি সংশোধন না করা এবং ইই / সিই সংস্করণগুলিতে ধাক্কা না দেওয়া পর্যন্ত স্টপ-গ্যাপ হিসাবে কাজ করা উচিত (এটি করার জন্য আমরা একটি এক্সটেনশন কিনে শেষ করেছি)।


0

আমি আপনাকে ফিলউইঙ্কল ডেডলকরেট্রি ইনস্টল করার পরামর্শ দিচ্ছি। এটি আমাদের ডাটাবেসের জন্য কাজ করে।

https://github.com/philwinkle/Philwinkle_DeadlockRetry

আমি আপনার ওয়েব এপিআই হিট আপনার বাইরের কোনও প্রোগ্রাম দেখার জন্যও পরামর্শ দেব। আমাদের কাছে এমন একটি ছিল যা পণ্যগুলির জন্য কিউটিওয়াই আপডেট করছিল এবং এটি অনেকগুলি অচলাবস্থার কারণ হয়েছিল। আমরা এটি আবার লিখেছি এবং সরাসরি ডাটাবেসে চলেছি।


1
এই রেপো আর সমর্থিত নয়, তবে ভাগ্যক্রমে এটি github.com/AOEpeople/Aoe_DbRetry এর প্রতিস্থাপনের প্রস্তাব দেয় ।
গুজ

-1

আমি গত বছর অচলাবস্থার সমস্যার সাথে অনেকবার মুখোমুখি হয়েছি I

আমিও মিরাভিস্ট ব্যবহার করেছিলাম আপনার অ্যাসিঙ্ক রিইনডেক্স সমাধান should

আরও স্থিতিশীল সিস্টেমের জন্য, আপনার ব্যাকএন্ডকে সম্মুখভাগ থেকে আলাদা করার কথা ভাবা উচিত যাতে তারা একে অপরের র‌্যাম না খায়।

আমার অভিজ্ঞতার জন্য, এটি উত্স কোডের সমস্যা নয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.