लेन-देन (Transactions)
Drupal ट्रांज़ैक्शन्स को भी सपोर्ट करता है, जिसमें उन डेटाबेस के लिए पारदर्शी (transparent) बैकअप विकल्प शामिल है जो ट्रांज़ैक्शन्स को सपोर्ट नहीं करते। हालांकि, यदि आप एक ही समय पर दो ट्रांज़ैक्शन्स चलाने की कोशिश करते हैं तो ट्रांज़ैक्शन्स काफी जटिल हो सकते हैं। इस स्थिति में व्यवहार भी डेटाबेस पर निर्भर करता है।
इसी तरह की समस्या C / C++ में नेस्टेड (nested) लॉक के साथ मौजूद होती है। यदि कोड पहले से लॉक A प्राप्त कर चुका है और फिर से लॉक A प्राप्त करने की कोशिश करता है, तो कोड ब्लॉक हो जाएगा। यदि आप ऐसा कोड लिखते हैं जो चेक करता है कि उसके पास पहले से लॉक है और उसे फिर से प्राप्त करने की कोशिश नहीं करता, तो आप डेडलॉक से बच जाते हैं, लेकिन लॉक को समय से पहले रिलीज़ कर सकते हैं।
SQL में भी हमारे पास वही समस्या है। यदि आपका कोड पहले से ट्रांज़ैक्शन में है, तो एक नया ट्रांज़ैक्शन शुरू करने का अप्रत्याशित और हानिकारक परिणाम यह होता है कि वर्तमान ट्रांज़ैक्शन पूरा हो जाता है और नया ट्रांज़ैक्शन शुरू हो जाता है।
Java इस नेस्टिंग समस्या को अपनी लॉकिंग सपोर्ट संरचना के जरिए हल करता है, जैसा कि नीचे परीक्षण किया गया है। Java आपको फ़ंक्शन्स को "synchronized" के रूप में मार्क करने की अनुमति देता है, जिससे फ़ंक्शन तब तक प्रतीक्षा करता है जब तक उसे लॉक नहीं मिल जाता और जब लॉक की आवश्यकता नहीं होती तो उसे रिलीज़ कर देता है। यदि एक synchronized फ़ंक्शन उसी क्लास में दूसरे synchronized फ़ंक्शन को कॉल करता है, तो Java लॉक की नेस्टिंग को ट्रैक करता है। बाहरी फ़ंक्शन लॉक प्राप्त करता है, आंतरिक फ़ंक्शन लॉक ऑपरेशन्स नहीं करता, और बाहरी फ़ंक्शन वापसी पर लॉक रिलीज़ करता है।
हालांकि हम PHP में फ़ंक्शन्स को "transactional" घोषित नहीं कर सकते, हम कंस्ट्रक्टर्स और डेस्ट्रक्टर्स वाले ऑब्जेक्ट्स का उपयोग करके Java की नेस्टिंग लॉजिक को इम्यूलेट कर सकते हैं। फ़ंक्शन बस "$transaction = $connection->startTransaction()" को पहली (या लगभग पहली) ऑपरेशन के रूप में कॉल करता है ताकि खुद को transactional बना सके। यदि एक transactional फ़ंक्शन दूसरे को कॉल करता है, तो हमारा ट्रांज़ैक्शन एब्स्ट्रैक्शन लेयर उन्हें नेस्ट करता है और अंदरूनी लेवल्स में transactional ऑपरेशन्स (डेटाबेस की दृष्टि से) निष्पादित नहीं करता।
नया ट्रांज़ैक्शन शुरू करने के लिए, बस अपने कोड में $transaction = $connection->startTransaction(); कॉल करें। ट्रांज़ैक्शन तब तक खुला रहेगा जब तक कि वेरिएबल $transaction स्कोप में रहता है। जब $transaction नष्ट हो जाता है, तो ट्रांज़ैक्शन कमिट हो जाएगा। यदि आपका ट्रांज़ैक्शन किसी दूसरे में नेस्टेड है, तो Drupal प्रत्येक ट्रांज़ैक्शन को ट्रैक करेगा और सबसे बाहरी ट्रांज़ैक्शन को तभी कमिट करेगा जब अंतिम ट्रांज़ैक्शन ऑब्जेक्ट स्कोप से बाहर हो जाएगा, अर्थात् सभी संबंधित क्वेरीज़ सफलतापूर्वक पूरी हो चुकी हों।
आपको $connection->startTransaction(); के रिटर्न वैल्यू को एक वेरिएबल को असाइन करना अनिवार्य है, जैसा कि उदाहरण में दिखाया गया है। यदि आप इस मेथड को कॉल करते हैं और रिटर्न वैल्यू को वेरिएबल में असाइन नहीं करते, तो आपका ट्रांज़ैक्शन तुरंत कमिट हो जाएगा, जिससे यह बेकार हो जाएगा।
ट्रांज़ैक्शन रोलबैक Drupal 8 में कनेक्शन ऑब्जेक्ट ($connection->rollBack()) द्वारा नियंत्रित किया जाता है, लेकिन सामान्यतः इसे ट्रांज़ैक्शन रैपर मेथड ($action->rollBack()) के माध्यम से करना चाहिए। इसका कारण यह है कि ट्रांज़ैक्शन का rollBack() मेथड इसे इसके नाम के आधार पर रोलबैक करता है, जबकि $connection->rollBack() डिफ़ॉल्ट रूप से नाम drupal_transaction सेट करता है और नेस्टेड ट्रांज़ैक्शन्स के साथ उपयोग करने पर अवांछित परिणाम दे सकता है।
उदाहरण:
function my_transaction_function() {
// यहाँ ट्रांज़ैक्शन शुरू होता है।
$transaction = $connection->startTransaction();
try {
$id = $connection->insert('example')
->fields([
'field1' => 'mystring',
'field2' => 5,
])
->execute();
my_other_function($id);
return $id;
}
catch (Exception $e) {
$transaction->rollBack();
watchdog_exception('my_type', $e);
}
// आप यहाँ $transaction को स्कोप से बाहर जाने दे सकते हैं और
// यदि इसे पहले से रोलबैक नहीं किया गया है, तो यह अपने आप कमिट हो जाएगा।
// हालाँकि, यदि आपको और काम करना है, तो आप खुद ट्रांज़ैक्शन को इस तरह कमिट कर सकते हैं:
$transaction->commit();
// यहाँ और कोड जो ट्रांज़ैक्शन के बाहर है।
}
function my_other_function($id) {
// यहाँ ट्रांज़ैक्शन अभी भी खुला है।
if ($id % 2 == 0) {
$connection->update('example')
->condition('id', $id)
->fields(['field2' => 10])
->execute();
}
}