कृपया त्रुटि संदेश से मूर्ख मत बनो The table 'my_table' is full
। इस दुर्लभ परिदृश्य का डिस्कसपेस से कोई लेना-देना नहीं है। इस तालिका को पूर्ण स्थिति में इनोबीडी की आंतरिक पाइपलाइन के साथ करना है।
सबसे पहले, InnoDB आर्किटेक्चर के इस आरेख पर एक नज़र डालें
कृपया ध्यान दें कि सिस्टम टेबलस्पेस (फ़ाइल ibdata) में केवल 128 रोलबैक सेगमेंट और 1023 रोलबैक स्लॉट प्रति रोलबैक सेगमेंट हैं। यह स्थान लेन-देन की रोलबैक क्षमता के आकार को सीमित करता है। दूसरे शब्दों में, यदि किसी लेन-देन का समर्थन करने के लिए एक एकल रोलबैक खंड को 1023 से अधिक स्लॉट की आवश्यकता होती है, तो लेनदेन उस table is full
स्थिति को प्रभावित करेगा ।
न्यू जर्सी में रेस्तरां रेड लॉबस्टर के बारे में सोचो । इसमें 200 लोगों की क्षमता हो सकती है। यदि रेस्तरां भरा हुआ है, तो लोगों की एक पंक्ति प्रतीक्षा करने के लिए बाहर जा सकती है। यदि लाइन पर लोग अधीर हो जाते हैं, तो वे छोड़ सकते हैं क्योंकि रेस्तरां भरा हुआ है। जाहिर है, इसका समाधान न्यू जर्सी को बड़ा बनाने (या अधिक विवाद होने) नहीं होगा। इसका समाधान रेड लॉबस्टर रेस्तरां को बड़ा बनाना होगा। इस तरह से आप बैठने की क्षमता को बढ़ा सकते हैं, मान लें कि 240। इसके साथ ही, यदि रेड लॉबस्टर में 240 से अधिक लोग आने का निर्णय लेते हैं, तो भी एक लाइन बाहर हो सकती है।
बस आपको एक उदाहरण देने के लिए, मेरे पास 2TB सिस्टम टेबलस्पेस और innodb_file_per_table के साथ एक क्लाइंट अक्षम था। (Ibdata1 के लिए 346G, ibdata2 के लिए रीसेट)। मैंने यह क्वेरी चलाई
SELECT SUM(data_length+index+length) InnoDBDataIndexSpace
FROM information_schema.tables WHERE engine='InnoDB';
इसके बाद, मैंने ibdata1 और ibdata2 के लिए फाइल के योग से InnoDBDataIndexSpace को प्रतिस्थापित किया। मुझे दो चीजें मिलीं जिन्होंने मुझे झकझोर दिया
- सिस्टम टेबलस्पेस के अंदर 106GB शेष था।
- मेरी भी यही
Table is Full
दशा हुई
इसका मतलब है कि 106GB इनोबीडी की आंतरिक पाइपलाइन के लिए उपयोग कर रहा था। क्लाइंट उस समय ext3 का उपयोग कर रहा था।
मेरे लिए समाधान ibdata3 जोड़ना था। मैंने अपने पुराने पोस्ट में इस बात पर चर्चा की कि "innodb_file_per_table" के साथ "तालिका ... पूर्ण" कैसे हल करें?
मैंने अन्य पोस्ट में भी इस पर चर्चा की है
ध्यान रखें कि यह स्थिति तब भी हो सकती है जब innodb_file_per_table सक्षम किया गया था। कैसे? रोलबैक और अन्डो लॉग्स अनियंत्रित स्पाइक का स्रोत हैं, जो ibdata1 के लिए विकास है ।
आपका वास्तविक प्रश्न
चूँकि आपकी तालिका में अनुक्रमणिका जोड़ रहे हैं और प्राप्त कर रहे हैं Table is Full
, तालिका बड़ी होनी चाहिए और एक एकल रोलबैक खंड के अंदर फिट नहीं हो सकती। आपको निम्न कार्य करना चाहिए:
कदम 01
डेटा को डंप फ़ाइल में प्राप्त करें
mysqldump --no-create-info mydb mytable > table_data.sql
चरण 02
MySQL में लॉगिन करें और इसे चलाएं
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
चरण 03
डेटा के साथ अतिरिक्त सूचकांक के साथ तालिका लोड करें
mysql -Dmydb < table_data.sql
बस इतना ही।
देखिए, समस्या यह है कि ALTER TABLE एकल लेनदेन के रूप में आपकी विशाल तालिका में सभी पंक्तियों को इंजेक्ट करने का प्रयास करेगा। Mysqldump का उपयोग करना एक समय में डेटा को तालिका में (अब एक नए सूचकांक के साथ) सम्मिलित करेगा, एक ही लेन-देन में सभी पंक्तियों को नहीं।
के बारे में चिंता मत करो what if this doesn't work?
मूल तालिका नाम दिया जाएगा mytable_old
कुछ भी करने के मामले में। यह एक बैकअप के रूप में काम कर सकता है। जब आप जानते हैं कि आपके लिए नई तालिका काम करती है तो आप बैकअप छोड़ सकते हैं।
कोशिश करो !!!
UPDATE 2014-06-16 11:13 EDT
यदि आप डेटा के डंप के बारे में चिंतित हैं बड़ा विशाल, बस इसे gzip।
आप एक ही चरण कर सकते हैं, लेकिन निम्नानुसार
कदम 01
डेटा को डंप फ़ाइल में प्राप्त करें
mysqldump --no-create-info mydb mytable | gzip > table_data.sql.gz
चरण 02
MySQL में लॉगिन करें और इसे चलाएं
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
चरण 03
डेटा के साथ अतिरिक्त सूचकांक के साथ तालिका लोड करें
gzip -d < table_data.sql.gz | mysql -Dmydb
या
gunzip < table_data.sql.gz | mysql -Dmydb
UPDATE 2014-06-16 12:55 EDT
मैंने इस मुद्दे के संबंध में एक और पहलू के बारे में सोचा।
चूंकि आप DDL कर रहे हैं और DML नहीं, इसलिए संभव है कि यह InnoDB आंतरिक पाइपलाइन न हो। चूंकि DDL InnoDB के लिए रोलबैक नहीं कर सकता , इसलिए समस्या को बाहरी प्लंबिंग होना चाहिए। यह बाहरी प्लंबिंग कहां से भरा हुआ है? मुझे ओएस के लिए अस्थायी फ़ोल्डर पर संदेह है। क्यों?
140616 13:04:33 InnoDB: Error: Write to file (merge) failed at offset 3 1940914176.
InnoDB: 1048576 bytes should have been written, only 970752 were written.
InnoDB: Operating system error number 0.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 0 means 'Success'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
140616 13:04:33 [ERROR] /usr/libexec/mysqld: The table 'my_table' is full
देखें disk quota exceeded
? यह डिस्क कोटा कहाँ लगाया जा रहा है?
इस क्वेरी को चलाएं
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
आपने कहा था /var/lib/mysqltmp
अब, इसे ओएस में चलाएं
df -h /var/lib/mysqltmp
कुछ मुझे बताता है कि अंतरिक्ष के लिए /var/lib/mysqltmp
बाहर चल रहा था सब के बाद, आप केवल 14G मुक्त है। डीडीएल (सूचकांक बनाने के लिए) की नजर में, एक रोलबैक हुआ, ibdata1 फ़ाइल में नहीं, बल्कि tmpdir
स्थान में। यदि /var/lib/mysqltmp
कहीं भी माउंट नहीं किया गया है, तो रूट विभाजन में अस्थायी डेटा लिखा जा रहा है। यदि /var/lib/mysqltmp
कहीं आरोहित किया गया है, तो उस माउंट को पंक्ति डेटा से भरा जा रहा है। किसी भी मामले में, डीडीएल को पूरा करने के लिए पर्याप्त जगह नहीं है।
आपके पास यहां दो विकल्प हैं
विकल्प 1
आप एक बड़ी डिस्क (शायद 100 + जीबी के साथ) बना सकते हैं और /var/lib/mysqltmp
उस बड़ी डिस्क पर माउंट कर सकते हैं।
विकल्प 2
मेरे 3-चरण के सुझावों को अभी भी काम करना चाहिए, यहां तक कि आपके पास सीमित डिस्कस्पेस भी
टीका
यह आपके द्वारा पोस्ट किया गया त्रुटि संदेश शर्म की बात है
InnoDB: Operating system error number 0.
InnoDB: Error number 0 means 'Success'.
इसका मतलब ओएस ठीक है। यह भी है कि इस स्थिति के लिए कोई संबद्ध त्रुटि संख्या मौजूद नहीं है।
एक और बात है जो आपको जाननी चाहिए। MySQL प्रलेखन का कहना है कि InnoDB के लिए फास्ट इंडेक्स क्रिएशन अभी भी डिस्क पर जाता है :
सूचकांक निर्माण के दौरान, फाइलें अस्थायी निर्देशिका (यूनिक्स पर $ TMPDIR, विंडोज पर% TEMP%, या --tmpdir कॉन्फ़िगरेशन चर) का मान लिखी जाती हैं। प्रत्येक अस्थायी फ़ाइल एक स्तंभ को पकड़ने के लिए पर्याप्त बड़ी होती है जो नए सूचकांक बनाती है, और जैसे ही इसे अंतिम सूचकांक में विलय कर दिया जाता है, प्रत्येक को हटा दिया जाता है।
MySQL की सीमा के कारण, तालिका को "फास्ट इंडेक्स क्रिएशन" का उपयोग करने के बजाय कॉपी किया जाता है, जब आप TEMPORARY TABLE पर एक इंडेक्स बनाते हैं। इसे MySQL Bug # 39833 के रूप में रिपोर्ट किया गया है ।
UPDATE 2014-06-16 13:58 EDT
[mysqld]
datadir = /mnt/cbsvolume1/var/lib/mysql
tmpdir = /mnt/cbsvolume1/var/lib/mysql
कृपया सुनिश्चित करें /mnt/cbsvolume1/var/lib/mysql
कि 100G या अधिक मुक्त है