मेज पर MySQL सूचकांक निर्माण विफल है


10

अद्यतन: tl? Dr: समस्या MySQL TMPDIRइंडेक्स बनाते समय उपयोग करता है। और मेरा TMPDIRएक डिस्क स्थान से बाहर चल रहा था।

मूल क्यू:

मैं एक InnoDB तालिका में एक सूचकांक जोड़ने की कोशिश कर रहा हूं, और ए table is full error। मेरे पास पर्याप्त डिस्क स्थान है और MySQL कॉन्फ़िगरेशन में फ़ाइल-प्रति-तालिका = 1 है। तालिका डेटा 85GB है और मुझे लगता है कि सूचकांक लगभग 20GB - 30GB होगा और मेरे पास इससे कहीं अधिक डिस्क स्थान है। मैं भी ext3 का उपयोग कर रहा हूं, इसलिए मुझे नहीं लगता कि OS बिंदु से फ़ाइल आकार की सीमा के साथ कोई समस्या है।

लॉग की गई त्रुटि इस तरह दिखती है:

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

यह क्या कारण है और मैं कैसे हल कर सकता हूं?

तालिका बनाएँ:

`CREATE TABLE `my_table` (
 `uid_from` bigint(11) NOT NULL,
 `uid_to` bigint(11) NOT NULL,
 `counter` int(11) NOT NULL,
 `updated` date NOT NULL,
 PRIMARY KEY (`uid_to`,`uid_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8`

जैसा कि डेटा 87.4GB है और मेरा अनुमान है कि लगभग 1.5B पंक्तियाँ हैं।

SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Variable_name   Value
tmpdir  /tmp

[root@web ~]# df -h /tmp
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       40G   24G   14G  64% /

1
"InnoDB: जांचें कि आपका OS और फ़ाइल सिस्टम इस आकार की फ़ाइलों का समर्थन करता है। InnoDB: यह भी जांचें कि डिस्क पूर्ण नहीं है या डिस्क कोटा पार नहीं हुआ है।" - क्या आपने जाँच की है? क्या आप ext2 का उपयोग कर रहे हैं? ext3? XFS? उपयोगकर्ता के लिए कोटा की जाँच की?
फिलु

@Phil ने दोनों को चेक किया। मैं ext3 का उपयोग कर रहा हूं और डिस्क स्थान के साथ कोई समस्या नहीं है। कूबड़ यह कुछ करने के लिए अपनी सीमा या कुछ तक पहुँचने लॉग के साथ क्या करना है, लेकिन वास्तव में कैसे सत्यापित करने और ठीक करने के लिए कोई विचार नहीं है।
नोआम

मुझे आश्चर्य है कि क्या फ़ाइल "(मर्ज)" है?
akuzminsky

@akuzminsky हम्म मुझे कोई पता नहीं है। मैंने केवल PHPMyAdmin से एक नया सूचकांक निर्माण चलाया।
नोआम

TMPDIR के लिए +1, मेरे सर्वर पर भी यही समस्या थी।
चाड ई।

जवाबों:


8

कृपया त्रुटि संदेश से मूर्ख मत बनो The table 'my_table' is full। इस दुर्लभ परिदृश्य का डिस्कसपेस से कोई लेना-देना नहीं है। इस तालिका को पूर्ण स्थिति में इनोबीडी की आंतरिक पाइपलाइन के साथ करना है।

सबसे पहले, InnoDB आर्किटेक्चर के इस आरेख पर एक नज़र डालें

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 या अधिक मुक्त है


डंप (85GB डेटा) से पहले स्थान पर तालिका बनाने में मुझे हफ्तों का समय लगा। क्या फिर से ऐसा करने के अलावा कोई और रास्ता नहीं है? क्या आप तालिका को विभाजित करने की सलाह देंगे?
नोम

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

लेकिन इस तालिका को बनाने से (फिर से) हमेशा के लिए ले जाएगा। रोलबैक विकल्प को अक्षम करते समय क्रिएट इंडेक्स चलाने का कोई तरीका?
नोआम

सूचकांक बनाना डीडीएल नहीं डीएमएल है। आप DDL व्यवहार नहीं बदल सकते। इसलिए मेरी पोस्ट डीएमएल तकनीकों का उपयोग करती है।
RolandoMySQLDBA

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