2010-09-06 19 views
7

समस्या: मेरे पास एक सारणी है जिसमें कुछ रिकॉर्ड हैं। सम्मिलित करने के बाद, मैं MySQL के sys_ * UDFs के माध्यम से एक बाहरी प्रोग्राम (php स्क्रिप्ट) कॉल करना चाहता हूं। अब, मुद्दा - ट्रिगर मैंने स्क्रिप्ट को रिकॉर्ड की आईडी पास कर दी है। जब मैं स्क्रिप्ट के माध्यम से डेटा खींचने की कोशिश करता हूं, तो मुझे 0 पंक्तियां मिलती हैं। अपने स्वयं के परीक्षण के दौरान, मैं एक निष्कर्ष पर आया कि ट्रिगर php स्क्रिप्ट को आमंत्रित करता है और वास्तविक डालने से पहले पैरामीटर पास करता है, इस प्रकार मुझे दिए गए आईडी के लिए कोई रिकॉर्ड नहीं मिलता है। मैंने इसका परीक्षण MySQL 5.0.75 और 5.1.41 (उबंटू ओएस) पर किया है। मैं पुष्टि कर सकता हूं कि वास्तविक डालने से पहले पैरामीटर स्क्रिप्ट में पास हो जाते हैं क्योंकि मैंने नींद (2) जोड़ दी है; मेरी PHP स्क्रिप्ट के लिए और मुझे डेटा सही ढंग से मिला है। नींद के बिना(); बयान, मुझे दिए गए आईडी के लिए 0 रिकॉर्ड प्राप्त हो रहे हैं।MySQL ट्रिगर - INSERT ट्रिगर + UDF sys_exec() समस्या

मेरा सवाल है - php स्क्रिप्ट के भीतर किसी प्रकार की देरी को हार्डकोड किए बिना इस समस्या को कैसे ठीक किया जाए? मुझे यह मानने की स्वतंत्रता नहीं है कि 2 सेकंड (या 10 सेकंड) पर्याप्त देरी होगी, इसलिए मैं सब कुछ "स्वाभाविक रूप से" प्रवाह करना चाहता हूं, जब एक आदेश समाप्त होता है - दूसरा निष्पादित हो जाता है।

मुझे लगता है कि यदि ट्रिगर इंसर्ट के बाद प्रकार का है, तो ट्रिगर के शरीर के भीतर सबकुछ निष्पादित हो जाएगा जब MySQL वास्तव में डेटा डालने के बाद निष्पादित हो जाएगा।

तालिका लेआउट:

CREATE TABLE test (
id int not null auto_increment PRIMARY KEY, 
random_data varchar(255) not null 
); 

उत्प्रेरक लेआउट:

DELIMITER $$ 

CREATE TRIGGER `test_after_insert` AFTER INSERT ON `test` 
FOR EACH ROW BEGIN 

SET @exec_var = sys_exec(CONCAT('php /var/www/xyz/servers/dispatcher.php ', NEW.id)); 
END; 
$$ 

DELIMITER ; 

अस्वीकरण: जब sys_exec समारोह का उपयोग कर रहा सुरक्षा के मुद्दों को पता है, मेरी समस्या यह है कि MySQL सम्मिलित नहीं है और फिर कहते हैं आवश्यक पैरामीटर के साथ लिपि। यदि कोई इसे ठीक करने के तरीके पर कुछ प्रकाश डाल सकता है या एक अलग दृष्टिकोण है जिसमें आउटपुट में चयन और एफएएम का उपयोग शामिल नहीं है - तो मैं बहुत आभारी हूं। अग्रिम में धन्यवाद।

+0

कृपया स्पष्ट करें: PHP स्क्रिप्ट dispatcher.php आग लगती है, आपके डेटा बेस पर क्लाइंट कनेक्शन स्थापित करती है, फिर कोई क्वेरी बनाती है? क्या वह सही है? –

+0

डेटा डाला जाता है। ट्रिगर को बुलाया जाता है और आईडी को dispatcher.php पर पास करता है। Dispatcher.php पंक्ति को पुनर्प्राप्त करता है और इसे ब्राउज़र पर भेजता है। कारण मैं सम्मिलित होने पर पूरा डेटा नहीं भेज रहा हूं क्योंकि मैं एक टेबल में डाल दूंगा लेकिन मैं डेटा को दृश्य से खींचूंगा - इसलिए मुझे किसी भी समय उपयोग किए जाने वाले सभी कॉलम नहीं पता हैं। – Mihael

+0

तो, dispatcher.php का अपना क्लाइंट कनेक्शन mySQL से है? यह भरोसेमंद काम नहीं करेगा, क्योंकि आपके ट्रिगर के बाद तक आपका ट्रिगर चलाने वाला सम्मिलित/अद्यतन लेनदेन पूरा नहीं होता है। तो, dispatcher.php या तो असंगत या पूर्व लेनदेन डेटा देखता है। किसी भी दर पर यह पाई का टुकड़ा खाने जैसा है जबकि पाई अभी भी ओवन में है। ट्रिगर डेटा बेस सर्वर के अंदर रहना चाहिए। –

उत्तर

3

यदि मैं इसे स्पष्ट रूप से समझता हूं, तो आप अपने डीबी में एक पंक्ति डालते हैं। यह एक ट्रिगर का आह्वान करता है जो PHP में लिखे गए बाहरी कमांड को लॉन्च करता है। सम्मिलित पंक्ति के आईडी का उपयोग कर उस कमांड क्वेरी को उसी डीबी में बदल दिया गया है?

मुझे नहीं लगता यह "देरी" की समस्या है।

असली "समस्या" आपका प्रारंभिक सम्मिलन है और आप बाहरी कमांड दो अलग-अलग sessions पर एक ही डीबी से कनेक्ट होते हैं - शायद दो अलग-अलग transactions (आपके डेटाबेस इंजन और आपके लेनदेन अलगाव स्तर के आधार पर)।

I मानते हैं, जब ट्रिगर में पंक्ति डालने का ट्रिगर अभी तक डीबी के लिए प्रतिबद्ध नहीं है। तो बाहरी कमांड अभी भी डीबी को देखता है जैसा कि पहले था।


BTW, अगर ऊपर दिया गया विवरण काफी काल्पनिक है - मुझे क्या अधिक स्पष्ट है कि आप शायद है कि काम किया जाता है के रूप में यह करने की कोशिश कर तुलना में एक अलग डिजाइन के बारे में सोचना चाहिए कि है।

2

भले ही आप ट्रिगर के बाद उपयोग करते हैं, पंक्ति अभी तक प्रतिबद्ध नहीं है। लेकिन sys_exec() php स्क्रिप्ट बाहर निकलने तक वापस नहीं आता है, इसलिए ट्रिगर के बाद पूरा नहीं हो सकता है, इसलिए आप INSERT को भी प्रतिबद्ध नहीं कर सकते हैं।

यह डिज़ाइन द्वारा है।आखिरकार, आप एक ही लेनदेन के भीतर और अधिक संचालन कर सकते हैं, या आप लेनदेन को वापस ले सकते हैं। एक ट्रिगर से बाहरी प्रक्रियाओं को आविष्कार करने में यह समस्या है: बाहरी प्रक्रिया डेटाबेस में लेनदेन के दायरे में डेटा नहीं देख सकती है।

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

+0

कमांड लाइन तर्क के माध्यम से आवश्यक डेटा पास करें? – JDPeckham

+0

@ जेडीपीकेम, सुनिश्चित करें कि आप पूरी पंक्ति को स्क्रिप्ट में पास कर सकते हैं। लेकिन क्या होगा यदि आईएनएसईआरटी एक लेनदेन का हिस्सा है जो आखिरकार वापस लुढ़का हुआ है? तब लिपि ने अभी डेटा पर काम किया है जो डेटाबेस में कभी दिखाई नहीं देगा। –

+0

धन्यवाद बिल! यह समझ आता है। मुझे लगता है कि किसी को अतिरिक्त प्रक्रिया या कुछ कॉल करना होगा। – JDPeckham

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