2011-08-03 21 views
5

मैं कई हज़ार सेंसर से रीडिंग एकत्र कर रहा हूं और उन्हें एक MySQL डेटाबेस में संग्रहीत कर रहा हूं। प्रति सेकंड कई सौ आवेषण हैं। सम्मिलित प्रदर्शन को बेहतर बनाने के लिए मैं शुरुआत में मानों को एक मेमरी बफर तालिका में संग्रहीत कर रहा हूं। एक बार एक मिनट में मैं एक संग्रहीत प्रक्रिया चलाता हूं जो मेमोरी बफर से स्थायी तालिका में डाली गई पंक्तियों को स्थानांतरित करता है।परमाणु रूप से एक टेबल से दूसरे टेबल पर पंक्तियों को कैसे स्थानांतरित करें?

मूल रूप से मैं अस्थायी बफर से पंक्तियों को स्थानांतरित करने के लिए अपने संग्रहीत प्रक्रिया में निम्नलिखित करना चाहते हैं: क्योंकि डेटा संग्रह की प्रक्रिया "data_buffer" में अतिरिक्त पंक्तियां सम्मिलित

INSERT INTO data SELECT * FROM data_buffer; 
DELETE FROM data_buffer; 

दुर्भाग्य से पिछले प्रयोग करने योग्य नहीं है INSERT के बीच और ऊपर हटाना। इस प्रकार उन पंक्तियों को "डेटा" तालिका में डाले बिना हटा दिया जाएगा।

मैं ऑपरेशन परमाणु कैसे बना सकता हूं या केवल पंक्तियों को हटाने के लिए डिलीट स्टेटमेंट बना सकता हूं जो पिछले कथन में चुने गए थे और इनसेरेट किए गए थे?

मैं इसे मानक तरीके से करना पसंद करूंगा जो संभवतः विभिन्न डेटाबेस इंजनों पर काम करता है।

मैं प्रदर्शन ओवरहेड और स्टोरेज आवश्यकताओं के कारण कोई अतिरिक्त "आईडी" कॉलम नहीं जोड़ना पसंद करूंगा।

काश SELECT_AND_DELETE या मानक SQL या कुछ इसी तरह में ले जाने के बयान था ...

+0

क्या आप data_buffer तालिका की संरचना प्रदान कर सकते हैं? –

+0

ज़रूर: 'टेबल बनाएं data_buffer' ( ' time' पूर्णांक (11) नहीं NULL, 'sensor' SMALLINT (6) नहीं NULL, ' मान' नाव नहीं NULL ) इंजन = स्मृति डिफ़ॉल्ट charset = latin1; – snap

+0

मेरे पास वास्तव में एक MySQL विशिष्ट समाधान है लेकिन ऐसा लगता है कि मुझे इसे 8 घंटे बीतने से पहले उत्तर अनुभाग में पोस्ट करने की अनुमति नहीं है। मैं वास्तव में stackoverflow में इन सीमाओं से नफरत करता हूं ... – snap

उत्तर

1

एक संभव तरीके से उन सभी समस्याओं से बचने के लिए, और भी तेजी से रहने के लिए, दो data_buffer तालिकाओं का उपयोग करने के लिए होगा (उन्हें data_buffer1 और data_buffer2 कॉल); जबकि संग्रह प्रक्रिया data_buffer2 में डालें, आप insert और deletedata_buffer2 पर कर सकते हैं; स्विच करने से, इसलिए एकत्रित डेटा data_buffer2 में जाता है, जबकि डेटा डाला जाता है + data_buffer1 से data में हटा दिया गया है।

+0

अंत में मैंने इस समाधान की एक भिन्नता लागू की: RENAME टेबल समाधान जिसे मैंने अपने उत्तर में लिखा था। हालांकि, क्योंकि यह इस उत्तर में विचार पर आधारित है, मैं इस उत्तर को मेरे स्वीकृत उत्तर के रूप में चुन रहा हूं। वैकल्पिक तालिकाओं का उपयोग करना मेरे मामले में सबसे अच्छा समाधान है क्योंकि रिकॉर्ड रखने वाले आईडी कॉलम से कोई अतिरिक्त ओवरहेड नहीं है और लॉकिंग के कारण सेंसर से आवेषण अवरुद्ध नहीं होंगे। – snap

3

मेरा मानना ​​है कि यह काम करेगा, लेकिन जब तक डालने

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
BEGIN TRANSACTION; 
INSERT INTO data (SELECT * FROM data_buffer FOR UPDATE); 
DELETE FROM data_buffer; 
COMMIT TRANSACTION; 
+0

नहीं। "अपडेट के लिए चुनें" केवल चयनित पंक्तियों को ताला लगाता है लेकिन नई पंक्तियों को इंसर्ट करने से नहीं रोकता है। – snap

+0

मैंने संपादित किया, .. उम्मीद है कि यह –

+0

क्षमा करें। दरअसल यह मेमरी टेबल (यदि एक ही लेनदेन में बनाया जाता है) के साथ काम करता है क्योंकि वे वर्तमान में केवल टेबल लेवल लॉक का समर्थन करते हैं। मैं वर्तमान स्टोरेज इंजन विशेषताओं पर निर्भर नहीं हूं, जो जानता है कि MySQL का अगला संस्करण मेमोरी टेबल के लिए पंक्ति स्तर ताले लागू करता है या कोई अस्थायी तालिका को एनडीबी मेमोरी टेबल (जो पंक्ति स्तर ताले का समर्थन करता है) में डालने का निर्णय लेता है। – snap

0

किया जाता है को अवरुद्ध कर देगा मुझे लगता है तालिकाओं समान हैं , एक ही कॉलम और प्राथमिक कुंजी के साथ? अगर ऐसा है, तो आप बसे एक जहां खंड के अंदर का चयन कर सकता है ... कुछ इस तरह:

DELETE FROM data_buffer 
WHERE primarykey IN (SELECT primarykey FROM data) 
+0

यदि कोई "प्राथमिककी" था तो यह काम करेगा। वर्तमान में ऐसा नहीं है क्योंकि अन्य प्रयोजनों के लिए इसकी आवश्यकता नहीं है। हालांकि मुझे लगता है कि यह बहुत धीमा होगा क्योंकि * डेटा * तालिका में ** विशाल ** पंक्तियां हैं। – snap

1

रिकॉर्ड कैसे एक पंक्ति आईडी होने के बारे में,, सम्मिलित होने से पहले अधिकतम मूल्य प्राप्त डालने और फिर हटाना < = अधिकतम (आईडी)

1

यह @ ammoQ के उत्तर का एक समान समाधान है। अंतर यह है कि INSERTING प्रक्रिया को रखने के बजाय कौन सी तालिका लिखना है, आप निर्धारित प्रक्रिया में तालिकाओं को पारदर्शी रूप से स्वैप कर सकते हैं।

उपयोग अनुसूचित प्रक्रिया में नाम बदलने टेबल स्वैप करने के लिए:

CREATE TABLE IF NOT EXISTS data_buffer_new LIKE data_buffer; 
RENAME TABLE data_buffer TO data_buffer_old, data_buffer_new TO data_buffer; 
INSERT INTO data SELECT * FROM data_buffer_old; 
DROP TABLE data_buffer_old; 

यह काम करता है क्योंकि RENAME बयान टेबल atomically अदला-बदली, इस प्रकार डालने प्रक्रियाओं के साथ "तालिका नहीं मिला" असफल नहीं होंगे। हालांकि यह MySQL विशिष्ट है।

0

यह एक MySQL विशिष्ट समाधान है। जब आप पंक्तियों को स्थानांतरित करते हैं तो नई पंक्तियों को जोड़ने से INSERTING प्रक्रियाओं को रोकने के लिए आप लॉकिंग का उपयोग कर सकते हैं।

प्रक्रिया है जो चाल पंक्तियों इस प्रकार होना चाहिए:

LOCK TABLE data_buffer READ; 
INSERT INTO data SELECT * FROM data_buffer; 
DELETE FROM data_buffer; 
UNLOCK TABLE; 

कोड जो आवेषण बफर में नई पंक्तियाँ इस प्रकार बदला जाना चाहिए:

LOCK TABLE data_buffer WRITE; 
INSERT INTO data_buffer VALUES (1, 2, 3); 
UNLOCK TABLE; 

सम्मिलित प्रक्रिया होगा स्पष्ट रूप से ब्लॉक जबकि ताला जगह में है।

+2

ऐसा प्रतीत होता है कि यह समाधान गलत है, क्योंकि संग्रहीत प्रक्रियाओं में लॉक टैबलेट का उपयोग करना संभव नहीं है (http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html)। दुर्भाग्य से मैं अपने उत्तर को कम नहीं कर सकता। :) – snap

संबंधित मुद्दे