2009-08-20 11 views
9

हमारे पास एक (वर्तमान में InnoDB) तालिका है जिसमें लगभग 500,000 पंक्तियां हैं। यह चलाने के लिए कार्यों की एक कतार का प्रतिनिधित्व करता है। यह एक MySQL डेटाबेस में संग्रहीत है।MySQL हटाने वाली पंक्तियों पर डेडलॉक्स

एक निरंतर आधार, प्रति सेकंड कम से कम एक बार, लेकिन कभी-कभी अधिक बार, हम इससे डेटा चुनते हैं और बाद में कुछ पंक्तियों को अपडेट करते हैं। प्रति दिन एक बार, हम मेज से पुरानी पंक्तियों को छीनते हैं।

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

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

मैं निम्नलिखित विकल्पों के देखते हैं, और राय चाहते हैं, जिस पर सबसे अच्छा, या अन्य विकल्पों के लिए सुझाव दिए गए हैं:

  1. एक समय
  2. हमारे हटाता पर घातीय backoff उपयोग पर कम पंक्तियां हटा देगा, हालांकि मैं मुझे चिंता है कि यह MySQL documentation के अनुसार हमारे विशिष्ट वर्कलोड
  3. लॉक टैबलेट को देने में सहायता नहीं करेगा। हम शायद हटाए गए समय की अवधि के लिए चयन और अद्यतन विवरणों को अवरुद्ध कर सकते हैं।
  4. MyISAM तालिका प्रकार पर स्विच करें। हम इनो डीबी के साथ गए क्योंकि हम शुरुआत में इस तालिका पर लेनदेन का उपयोग कर रहे थे। यह अब मामला ही नहीं है। मैं यह जानने के लिए विशिष्ट रूप से परिचित नहीं हूं कि यह एक व्यवहार्य समाधान है या नहीं।
  5. शायद अद्यतन LOW_PRIORITY का उपयोग करें। हो सकता है कि DELETEs SELECTs को प्रभावित न करें, केवल अद्यतन, और यह पर्याप्त हो सकता है।
+1

मेरे सामने आने वाले सभी डेडलॉक्स असामान्य लेनदेन के कारण हैं। सुनिश्चित करें कि आप सही तरीके से चल रहे लेनदेन कर रहे हैं (या तो ऑटोकॉमिट पर या ऑटोोकॉमिट ऑफ और वास्तव में काम/रोलबैक को संभालने)। – localshred

+0

निश्चित रूप से एक अच्छा बिंदु; यह ज्यादातर समय होगा लेकिन हम वास्तव में इस तालिका पर लेनदेन नहीं कर रहे हैं। हम करते थे, लेकिन अब नहीं करते थे। – ChrisInEdmonton

उत्तर

4

जब DML संचालन, InnoDB ताले प्रदर्शन सभी पंक्तियां स्कैन की गईं, मिलान नहीं हुईं।

इस तालिका लेआउट पर विचार करें:

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

INSERT 
INTO t_tran 
VALUES 
(1, 1), 
(2, 2), 
(3, 3), 
(4, 4), 
(5, 5), 
(6, 6), 
(7, 7), 
(8, 8); 

START TRANSACTION; 

DELETE 
FROM t_tran 
WHERE data = 2 
     AND id <= 5; 

इस मामले में, MySQL का चयन करता है id पर RANGE पहुंच पथ है, जो यह data पर सस्ता की तुलना में REF समझता है।

एक समवर्ती लेनदेन में, आप 15 को नष्ट करने के लिए या अद्यतन पंक्तियों 6, 7, 8 नहीं बल्कि पंक्तियों में सक्षम है क्योंकि वे (तथ्य यह है कि केवल पंक्ति 2 प्रभावित था के बावजूद) बंद हैं हो जाएगा।

यदि आप ऊपर दी गई स्थिति से id <= 5 हटाते हैं, तो आप किसी भी पंक्ति को हटाने में सक्षम होंगे लेकिन पंक्ति 3

दुर्भाग्यवश, आप DML संचालन में MySQL पहुंच पथ को नियंत्रित नहीं कर सकते हैं।

सर्वश्रेष्ठ आप अपनी शर्तों को ठीक से अनुक्रमणित कर सकते हैं और उम्मीद कर सकते हैं कि MySQL इन इंडेक्स को चुनेंगे।

+0

धन्यवाद, हम (मेरे sysadmin और I) राय के हैं कि यह वास्तव में शायद सबसे अच्छा तय है। हमने हटाने और अतिरिक्त घातीय बैकऑफ जोड़ने की मात्रा भी कम कर दी है। हम देखेंगे कि क्या समस्या का ख्याल रखता है। – ChrisInEdmonton

1

सुनिश्चित करें कि आपके लेनदेन अलगाव को पढ़ने के रूप में चिह्नित किया गया है और दोहराने योग्य नहीं पढ़ा जा सकता है। पढ़ें पढ़ें डिफ़ॉल्ट होना चाहिए, लेकिन हमने देखा कि हमारे सर्वर में innodb डिफ़ॉल्ट दोहराया जा सकता था।

आप चलाकर जांच कर सकते हैं निम्नलिखित:

SHOW VARIABLES LIKE 'tx%'; 

, इस सेट करने के लिए अपने my.cnf फ़ाइल में folloiwing लाइन में प्रवेश के लिए आदेश में:

tx_isolation=READ-COMMITTED 
संबंधित मुद्दे