मैंने लंबे समय से सोचा है कि जेडीबीसी एपीआई एक ऑटोोकॉमिट मोड प्रदान करता है (java.sql.Connection.setAutocommit()
)। यह एक आकर्षक उपद्रव की तरह लगता है जो लोगों को परेशानी में डाल देता है। मेरा सिद्धांत यह है कि इसे केवल जेडीबीसी में जोड़ा गया ताकि विक्रेताओं के लिए जीवन को सरल बनाया जा सके जो जेडीबीसी का उपयोग करके एसक्यूएल को संपादित करने और चलाने के लिए उपकरण बनाना चाहते थे। क्या ऑटोोकॉमिट चालू करने का कोई अन्य कारण है, या क्या यह हमेशा एक गलती है?Autocommit को सही क्यों सेट करें?
उत्तर
दुर्भाग्य से, ऑटोोकॉमिट का उपयोग डेटाबेस विशिष्ट (लेनदेन व्यवहार के रूप में) है। मुझे लगता है कि यदि आपके पास वैश्विक, प्रोग्रामेटिक लेन-देन रणनीति नहीं है, तो ऑटोकॉमिट शायद उम्मीद कर रहा है कि हर कोई सही ढंग से लेनदेन को बंद/रोल करता है।
MySQL के लिए बोलते हुए, आप डिफ़ॉल्ट रूप से autocommit = true को छोड़ सकते हैं, और जब आप लेनदेन करते हैं तो यह स्वचालित रूप से बंद हो जाएगा। Autocommit = false सेट करने का एकमात्र कारण यह है कि यदि कोई BEGIN के बिना लेनदेन शुरू करने का प्रयास करता है तो आप एक त्रुटि को मजबूर करना चाहते हैं।
आज सामान्य जावा + माईएसक्यूएल एप्लिकेशन में सादगी के लिए, मैं ऑटो-प्रतिबद्ध सेटिंग को कम या ज्यादा अनदेखा करता हूं, ओपन-सत्र-इन-व्यू पैटर्न का उपयोग करता हूं और इसे अच्छा कहता हूं।
मैं स्पष्ट रूप से स्पष्ट आरडीबीएमएस पंक्ति ताले को हतोत्साहित करता हूं और इसके बजाय आशावादी ताले का उपयोग करता हूं। हाइबरनेट आशावादी ताले के लिए अंतर्निहित समर्थन प्रदान करता है, लेकिन यह हाथ से लुढ़का कोड के लिए भी अपनाने के लिए एक आसान पैटर्न है और बेहतर प्रदर्शन प्रदान करता है।
कमिट-मोड डीबी को ताले रखने के तरीके को बदलता है।
केवल लेनदेन मोड के दौरान ऑटो-प्रतिबद्ध मोड को अक्षम करने की सलाह दी जाती है। इस तरह, आप एकाधिक बयानों के लिए डेटाबेस ताले रखने से बचते हैं, जो अन्य उपयोगकर्ताओं के साथ संघर्ष की संभावना को बढ़ाता है।
...
एक लेनदेन के दौरान टकराव से बचने के लिए, एक डीबीएमएस डेटा है कि लेनदेन द्वारा पहुँचा जा रहा करने के लिए दूसरों के द्वारा पहुँच को अवरुद्ध करने के लिए ताले, तंत्र का उपयोग करता है। (ध्यान दें कि स्वतः-मोड, जहां प्रत्येक बयान एक सौदे में, ताले केवल एक बयान के लिए आयोजित की जाती हैं।)
http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html
यह देखते हुए कि यहां तक कि mySQL और DB2 भी इन दिनों बहु-संस्करण हैं, यह ट्यूटोरियल कुछ हद तक अनैतिक हो रहा है। :( – Affe
स्नैपशॉट अलगाव स्तर मुफ्त में नहीं आते हैं: http://blogs.msdn.com/b/sqlserverstorageengine/archive/2008/03/30/overhead-of-row-versioning.aspx आपको स्नैपशॉट अलगाव के साथ समेकन प्राप्त होता है , लेकिन आप ओवरहेड जोड़ते हैं। – hythlodayr
लॉक प्राप्त करने के तरीके को समझना हमेशा प्रासंगिक होता है। –
केवल उचित कारण मैं देख सकता हूँ connection.commit()
और से छुटकारा पाने के लिए है छोटे अनुप्रयोगों में सरल एकल-क्वेरी लेनदेन में connection.rollback()
बॉयलरप्लेट। कच्चे रूप में जेडीबीसी के लिए पहले से ही बहुत सारे बॉयलरप्लेट की आवश्यकता है। प्रत्येक पंक्ति कम जेडीबीसी शुरुआत करने वालों को कम डरावनी बनाता है।
9 5% कोडबेस जो मैं अभी काम कर रहा हूं, में एक ही अपडेट शामिल है जहां ऑटोकॉमिट पर पूरी तरह से उचित है। तो, हम इसके लिए डिफ़ॉल्ट हैं। केवल उस लेन-देन की आवश्यकता वाले कोड के अनुभागों को करने के लिए पर्याप्त रूप से इसे बंद कर दें, फिर ऑटोकॉमिट सही हो जाता है!
कृपया ध्यान रखें कि लेनदेन आपको अपने लेनदेन प्रबंधक से लेनदेन का समय भी दे सकता है। क्या आप अपने प्रत्येक प्रश्न पर टाइमआउट सेट करते हैं? –
मैं लगभग हमेशा autocommit = true के साथ चलाता हूं। 99% समय, मेरे अपडेट परमाणु हैं। निश्चित रूप से, ऐसे मामले हैं जहां आप डेबिट लिखते हैं और फिर उस क्रेडिट को लिखने में असफल हो जाते हैं जिसे आप रोलबैक करना चाहते हैं। लेकिन मेरे अनुभव में, ये अपेक्षाकृत दुर्लभ हैं। आमतौर पर जो रिकॉर्ड मैं लिखता हूं वह स्वयं ही होता है। उस स्थिति में, प्रत्येक लेखन के बाद प्रतिबद्ध करने के साथ परेशान करने की आवश्यकता नहीं है। यह यहां और वहां कोड की एक पंक्ति को बचाता है। यदि प्रोग्राम की संरचना दी गई है, तो इसका अर्थ यह है कि मुझे अतिरिक्त प्रयास/पकड़ ब्लॉक की आवश्यकता नहीं है या मुझे कार्यों के बीच कनेक्शन ऑब्जेक्ट को पास करने की आवश्यकता नहीं है। यह कष्टप्रद कीड़े पर बचाता है जहां कोई प्रतिबद्धता भूल गया।
एकमात्र तरीका है कि मैं देखता हूं कि यह "किसी को परेशानी में लुभाने" सकता है, क्या वह निर्णय लेता है कि ऑटोकॉमिट बंद करना और प्रतिबद्धता या रोलबैक करना बहुत अधिक परेशानी है और इसलिए वह अद्यतन करता है जो व्यक्तिगत रूप से लेनदेन के भीतर होना चाहिए। तब सबकुछ ठीक काम करने के लिए एपर्स करता है जब तक कि कुछ भी नहीं होता है जो लेनदेन को रोकना चाहिए। यदि परीक्षण परिदृश्य अपर्याप्त हैं, तो मैं कल्पना कर सकता हूं कि यह उत्पादन में फिसल रहा है।
लेकिन आप किसी भी भाषा की लगभग किसी भी विशेषता के बारे में ऐसा कह सकते हैं। जैसे, मान लें कि आप एक प्रोग्राम लिखते हैं जो संख्याओं को संसाधित करता है कि 90% समय लंबे समय तक फिट होगा, लेकिन हर अब और फिर बड़ा हो सकता है। इस स्थिति के साथ सामना करने के लिए, बिगइंटर का उपयोग करना या बड़ी संख्याओं को संभालने के लिए एक नई कक्षा बनाना है। एक आलसी प्रोग्रामर लंबे समय तक उपयोग करने में लुप्त हो सकता है क्योंकि यह आमतौर पर काम करेगा और अन्य विकल्प बहुत अधिक परेशानी हैं। इसलिए आप निष्कर्ष निकालेंगे कि जावा में लंबे समय तक (या int) शामिल नहीं होना चाहिए क्योंकि जब कोई उचित नहीं है तो किसी को उनका उपयोग करने में लालसा हो सकता है?
यदि आपके कार्यक्रमों में अधिकांश लेनदेन संदर्भ के भीतर अपडेट किए जाने हैं, तो ऑटोकॉमिट बंद करें। इसकी उपस्थिति आपको किसी को भी चोट नहीं पहुंचाती है। यह सुविधाजनक है, जब यह सुविधाजनक है, लेकिन जब यह नहीं है तो आप इसे बंद कर सकते हैं।
जेडीबीसी 3 spec के बाद से, "ऑटो-प्रतिबद्ध" मोड में कनेक्शन में एक से अधिक वक्तव्य खुले नहीं हो सकते हैं। इस प्रकार, बाहरी चयन लूप के भीतर नेस्टेड अद्यतन या यहां तक कि चयन समस्याएं पैदा करेगा। –
यह केवल परमाणुता नहीं है, लेनदेन प्रबंधक भी इसका समर्थन करता है अगर लेनदेन प्रबंधक इसका समर्थन करता है। ऑटोोकॉमिट और कोई क्वेरी टाइमआउट का उपयोग करने से आपको पता नहीं लगाया जा सकता है कि एसक्यूएल प्रदर्शन की समस्याएं, भारी प्रश्नों को लटका दिया गया है। –
मैं कई वर्षों से जावालैंड से बाहर हूं इसलिए शायद जावा के नए संस्करण अलग हैं या मैं सिर्फ चीजों को गलत समझा रहा हूं। लेकिन मुझे पूरा यकीन है कि ऑटोकॉमिट के साथ प्रश्न निष्पादित करते समय मुझे एसक्यूएल टाइमआउट मिल गया। मुझे उन प्रश्नों की कई यादगार यादें हैं जो विकास पर्यावरण में पाई गईं लेकिन प्रोड में समय समाप्त हो गईं। शायद डिफ़ॉल्ट अलग या कुछ हैं। किसी भी मामले में, आपको यह बताने के लिए एक टाइमआउट पर भरोसा है कि आपके पास एक प्रदर्शन समस्या है एक बहुत ही बदमाश उपकरण है। – Jay
ऑटो-प्रतिबद्धता सुविधाजनक है; लेकिन जेडीबीसी 3 spec में परिवर्तन के साथ, बहुत कम उपयोगी हो गया है।
चूंकि "ऑटो-प्रतिबद्ध" मोड में जेडीबीसी 3 कनेक्शन में एक से अधिक वक्तव्य खुले नहीं हो सकते हैं। किसी अन्य कथन को निष्पादित करना, पहले को बंद कर देगा - किसी भी परिणामसेट सहित।
इस प्रकार, एक चयन के भीतर लूपिंग और अद्यतन जारी करने (या यहां तक कि नेस्टेड SELECTs) विफल हो जाएंगे। जाहिर है यह एक अपराध है, वास्तव में अपने बाहरी चयन के परिणामों के साथ कुछ करना चाहते हैं!
वैसे भी, विशिष्ट ड्राइवर & संस्करण पर निर्भर करता है .. लेकिन सामान्य रूप में JDBC 3 कल्पना इस बेकार व्यवहार जनादेश प्रतीत होता है। ड्राइवरों को अपग्रेड करने से भी इस व्यवहार को 'अनजाने' मिल सकता है।
ऑटो-प्रतिबद्ध का उपयोग क्यों करें? मूल रूप से, यह उपयोगी था & सुविधाजनक। अन्य उत्तर कहना के रूप में, JDBC बक और हैंडलिंग के प्रचुर मात्रा में आवश्यकता होती है सही ढंग से कॉल करने के लिए .. JDBC वास्तव में एक अच्छी तरह से डिजाइन एपीआई :(हाइबरनेट या वसंत के JdbcTemplate का उपयोग कर
इन दिनों, तुम बेहतर होगा नहीं है। और यदि आप servlets/web ऐप्स कर रहे हैं, तो "उपयोगकर्ता अनुरोध" की सीमाओं पर अपने लेन-देन प्रबंधन (प्रारंभ/समाप्ति) या हाइबरनेट सत्र (इसे थ्रेड-लोकल में बाध्य करें) रखें।
उदाहरण के लिए, प्राप्त करें ServletRequest की शुरुआत में अपना कनेक्शन/लेनदेन बांधें और इसे अंत में वापस कर दें।
आप javax.servlet.filter या इसी तरह का उपयोग कर सकते हैं, और इसे बांध सकते हैं एक धागे की स्थानीय करने के लिए, यह आवश्यकता, आदि एक स्थिर सहायक इसे पाने के लिए कर सकते हैं या
कृपया वेब अनुरोध एएनटीआई पैटर्न से जुड़े कनेक्शन/लेनदेन/सत्र को पुनः प्राप्त न करें ... यदि आप अपने लेनदेन को विस्तारित करना चाहते हैं उदा।अनुरोध प्रसंस्करण, मल्टीप्लार्ट अपलोड प्रोसेसिंग, ग्राहक को धीरे-धीरे कनेक्शन के साथ क्लाइंट को भेजना, आप इसे कर सकते हैं, लेकिन मैं लगभग सभी मामलों में यह बहुत बुरा विचार कहूंगा। –
धन्यवाद @ PiotrMüller - कोई तर्क या संदर्भ? मुझे उम्मीद है कि आप लगभग किसी भी पैटर्न के लिए 0.001% खराब मामले के साथ आ सकते हैं, लेकिन "लगभग सभी मामलों" होने से "पृथक समस्याग्रस्त कोने के मामले संभव हैं" को अलग करना संभव है - और उस समय मैंने यह सिफारिश दी (2012), मुझे विश्वास है कि यह अच्छी सलाह थी। उपयोगकर्ता अनुरोध सीमा एक HTTP सर्विसिंग अनुप्रयोग में सबसे मौलिक और महत्वपूर्ण सीमा है। इसके कारण, यह डिजाइन करने के लिए एक मजबूत और स्पष्ट उम्मीदवार है। कोई भी वैकल्पिक समाधान अधिक जटिल होगा। वेब अनुप्रयोग में –
सबसे अधिक "खराब केस" लागू होगा (किसी भी सामान्य वेब ऐप के लिए)। सत्र को सक्षम करने में आपको यह सुनिश्चित करना चाहिए कि बहुत से तकनीकी तकनीकी पहलुओं को तुरंत संबोधित किया जाए। प्रतिक्रिया बफरिंग: सुनिश्चित करें कि लेनदेन और एसक्यूएल कनेक्शन क्लाइंट कनेक्शन के पूरे समय प्रतिक्रिया को खींचने के लिए नहीं है (क्लाइंट कम बैंडविड्थ होने पर लंबे समय तक एसक्यूएल कनेक्शन क्यों पकड़ें)। अगर यह बहुत जल्दी डिजाइन/प्रदर्शन समस्याओं में ड्राइव करता है तो आवेदन बढ़ता है। एक त्वरित, कुछ हफ्तों की छोटी परियोजना के लिए यह कुछ समाधान हो सकता है, लेकिन मैं इसे –
वैसे वहाँ कुछ शर्तों कि सावधान देखो की जरूरत है, जबकि सक्रिय करने के वैश्विक स्तर पर "स्वत: प्रतिबद्ध" कर रहे हैं:
ए।) प्रश्न स्तर पर लेनदेन प्रबंधन उपयोगकर्ता को छोड़ा जाएगा, उदाहरण के लिए यदि किसी को सफल होने या विफल होने के लिए प्रश्नों की गुच्छा की आवश्यकता है तो उसे BEGIN के तहत लपेटने और लेनदेन करने की आवश्यकता है।
बी।) याद रखें, "ऑटो-प्रतिबद्ध" सक्षम होने पर कोई रोलबैक नहीं है।
सी।) प्रत्येक लेनदेन को लिखने (काम करने) का एक ओवरहेड भी है।
डी।) केवल पढ़ने के लिए प्रश्नों को "ऑटो-प्रतिबद्ध" की कोई स्पष्ट आवश्यकता नहीं है, लेकिन "ऑटो-प्रतिबद्ध" सक्षम करके यह सभी प्रश्नों के लिए स्वचालित रूप से लागू होता है।
यदि टेबल लॉकिंग ऑटो-प्रतिबद्ध करने में सक्षम होने की एकमात्र चिंता है तो यह एक अच्छा विचार नहीं हो सकता है, बल्कि कोई लॉक टाइमआउट का सहारा ले सकता है।
विशिष्ट जाव को स्पष्ट करने के लिए va + MySQL अनुप्रयोग: ऑटो-प्रतिबद्ध सेट को सत्य पर छोड़ दें। आने वाले अनुरोध (या तो एक वेब पेज या एक आरईएसटी/जेएसओएन) की शुरुआत में, एक सत्र (और एक लेनदेन शुरू करें) खोलें। अगर अनुरोध सामान्य रूप से प्रक्रिया करता है, तो अनुरोध प्रसंस्करण के अंत में लेनदेन प्रतिबद्ध करें। फिर, अनुरोध के लिए अपने 500 पेज प्रतिपादन में एक रोल वापस जोड़ें। यह मूल रूप से प्ले फ्रेमवर्क चीजों को कैसे संभालता है, उदाहरण के लिए। यह उपयोगकर्ता और डेवलपर के लिए सहज है। –
यह एक अच्छा जवाब है - "वेब अनुरोध" को वेबपैप में "डीबी लेनदेन" से काफी सहसंबंध होना चाहिए। इस प्रकार हमें आशावादी पर भरोसा करने की जरूरत है, डीबी लॉकिंग नहीं। यह पूरे अनुरोध के माध्यम से एक सत्र खोलने के लिए OpenSessionInView का उपयोग करने में मदद करता है, जिसमें प्रतिपादन देखें, और फिर अनुरोध के अंत में फ़्लश/प्रतिबद्ध करें। –
मेरी राय में यह एक अच्छा जवाब नहीं है, यदि सामान्य जावा + MySQL एप्लिकेशन "कुछ हफ्तों के लिए प्रोजेक्ट" से अधिक कुछ है, तो एंटीपेटर्न के रूप में सत्र-खुले-इन-व्यू पर विचार करें। आपके आवेदन में जो कुछ हो रहा है, उसमें आप जल्दी से नियंत्रण खो देंगे, यह व्यावहारिक रूप से प्रदर्शन या समवर्ती समस्याओं के लिए ड्राइव सुनिश्चित करेगा, ऑटोोकॉमिट आपको "सामान्य अनुरोध प्रसंस्करण टाइमआउट" के रूप में काम कर रहे लेनदेन टाइमआउट या लेन-देन टाइमआउट के बिना छोड़ देगा। मैं कहूंगा कि वेब अनुरोध 90% से अधिक मामलों में एसक्यूएल लेनदेन में कोई सहसंबंध नहीं है –