फ्रेमवर्क के पास यह जानने का कोई तरीका नहीं है कि आपने कोई लेन-देन शुरू किया है या नहीं। आप $db->query('START TRANSACTION')
. का भी उपयोग कर सकते हैं जिसके बारे में फ्रेमवर्क को पता नहीं होगा क्योंकि यह आपके द्वारा निष्पादित SQL कथनों को पार्स नहीं करता है।
मुद्दा यह है कि यह ट्रैक करने के लिए एक आवेदन जिम्मेदारी है कि आपने लेनदेन शुरू किया है या नहीं। यह ऐसा कुछ नहीं है जो ढांचा कर सकता है।
मुझे पता है कि कुछ ढांचे इसे करने की कोशिश करते हैं, और कॉकमामी चीजें करते हैं जैसे गिनती करते हैं कि आपने कितनी बार लेनदेन शुरू किया है, केवल तभी इसे हल करें जब आपने कई बार मिलान किया हो या रोलबैक किया हो। लेकिन यह पूरी तरह से फर्जी है क्योंकि आपका कोई भी कार्य यह नहीं जान सकता है कि क्या प्रतिबद्ध या रोलबैक वास्तव में ऐसा करेगा, या यदि वे घोंसले के शिकार की दूसरी परत में हैं।
(क्या आप बता सकते हैं कि मैंने यह चर्चा कई बार की है? :-)
अपडेट 1: प्रोपेल एक PHP डेटाबेस एक्सेस लाइब्रेरी है जो "आंतरिक लेनदेन" की अवधारणा का समर्थन करती है जो आपके द्वारा बताए जाने पर प्रतिबद्ध नहीं होती है। लेन-देन शुरू करने से केवल एक काउंटर बढ़ता है, और काउंटर को कमिट/रोलबैक घटाता है। नीचे एक मेलिंग सूची थ्रेड का एक अंश है जहां मैं कुछ परिदृश्यों का वर्णन करता हूं जहां यह विफल हो जाता है।
अपडेट 2: डॉक्ट्रिन डीबीएएल में भी यह विशेषता है। वे इसे ट्रांजेक्शन नेस्टिंग कहते हैं।
यह पसंद है या नहीं, लेन-देन "वैश्विक" हैं और वे ऑब्जेक्ट-ओरिएंटेड एनकैप्सुलेशन का पालन नहीं करते हैं।
समस्या परिदृश्य #1
मैं कॉल करता हूं commit()
, क्या मेरे परिवर्तन प्रतिबद्ध हैं? अगर मैं "आंतरिक लेनदेन" के अंदर चल रहा हूं तो वे नहीं हैं। बाहरी लेन-देन को प्रबंधित करने वाला कोड वापस रोल करना चुन सकता है, और मेरे परिवर्तन मेरी जानकारी या नियंत्रण के बिना छोड़ दिए जाएंगे।
उदाहरण के लिए:
- मॉडल ए:लेनदेन शुरू करें
- मॉडल ए:कुछ परिवर्तन निष्पादित करें
- मॉडल बी:लेन-देन शुरू करें (साइलेंट नो-ऑप)
- मॉडल बी:कुछ परिवर्तन निष्पादित करें
- मॉडल बी:कमिट (साइलेंट नो-ऑप)
- मॉडल ए:रोलबैक (मॉडल ए परिवर्तन और मॉडल बी परिवर्तन दोनों को छोड़ देता है)
- मॉडल बी:डब्ल्यूटीएफ!? मेरे परिवर्तनों का क्या हुआ?
समस्या परिदृश्य #2
एक आंतरिक लेनदेन वापस आ जाता है, यह बाहरी लेनदेन द्वारा किए गए वैध परिवर्तनों को त्याग सकता है। जब बाहरी कोड पर नियंत्रण वापस किया जाता है, तो यह मानता है कि इसका लेनदेन अभी भी सक्रिय है और प्रतिबद्ध होने के लिए उपलब्ध है। आपके पैच के साथ, वे commit()
. को कॉल कर सकते हैं , और चूंकि transDepth अब 0 है, यह चुपचाप $transDepth
सेट करेगा टू -1 और कुछ भी न करने के बाद सही लौटें।
समस्या परिदृश्य #3
अगर मैं commit()
. को कॉल करता हूं या rollback()
जब कोई लेन-देन सक्रिय नहीं होता है, तो यह $transDepth
. सेट करता है से -1. अगला beginTransaction()
स्तर को 0 तक बढ़ा देता है, जिसका अर्थ है कि लेन-देन को न तो वापस लाया जा सकता है और न ही प्रतिबद्ध किया जा सकता है। commit()
. के बाद के कॉल लेन-देन को घटाकर -1 या उससे आगे कर देगा, और आप तब तक प्रतिबद्ध नहीं हो पाएंगे जब तक कि आप एक और ज़रूरत से ज़्यादा नहीं करते beginTransaction()
स्तर फिर से बढ़ाने के लिए।
मूल रूप से, डेटाबेस को बहीखाता पद्धति करने की अनुमति दिए बिना एप्लिकेशन लॉजिक में लेनदेन को प्रबंधित करने का प्रयास करना एक बर्बाद विचार है। यदि आपके पास एक आवेदन अनुरोध में स्पष्ट लेनदेन नियंत्रण का उपयोग करने के लिए दो मॉडलों की आवश्यकता है, तो आपको दो डीबी कनेक्शन खोलने होंगे, प्रत्येक मॉडल के लिए एक। फिर प्रत्येक मॉडल का अपना सक्रिय लेन-देन हो सकता है, जिसे एक दूसरे से स्वतंत्र रूप से किया या वापस लाया जा सकता है।