2012-09-27 18 views
26

हटाने का आदेश तय करने का तरीका है सबसे पहले हाइबरनेट के बारे में भूल जाएं। मान लें कि मेरे पास दो टेबल हैं, ए & बी। दो लेन-देन इन दो तालिकाओं में एक ही रिकॉर्ड अपडेट कर रहे हैं, लेकिन टीएक्सएन 1 अपडेट बी और फिर ए, जबकि टीएक्सएन 2 अपडेट ए तो बी। यह एक सामान्य डेडलॉक उदाहरण है। इससे बचने का सबसे आम तरीका संसाधनों को प्राप्त करने के आदेश को पूर्व परिभाषित करना है। उदाहरण के लिए, हमें टेबल ए अपडेट करना चाहिए बीहाइबरनेट अद्यतन/डालने/

हाइबरनेट पर वापस जाएं। जब हम एक सत्र में कई संस्थाओं को अपडेट कर रहे हैं, एक बार जब मैं सत्र को फ्लश कर रहा हूं, तो विभिन्न संस्थाओं के परिवर्तन डीबी को संबंधित सम्मिलित/अद्यतन/हटाए गए बयान उत्पन्न करने जा रहे हैं। क्या हाइबरनेट में कुछ एल्गोरिदम हैं जो संस्थाओं के बीच अद्यतन के आदेश का निर्णय लेते हैं? यदि नहीं, तो पहले पैराग्राफ में वर्णित डेडलॉक स्थिति को रोकने के लिए हाइबरनेट किस तरह से उपयोग किया जाता है?

यदि हाइबरनेट आदेश बनाए रखता है, तो मैं आदेश को कैसे जानता या नियंत्रित कर सकता हूं? मैं नहीं चाहता कि डीबी में मेरा स्पष्ट अपडेट हाइबरनेट के साथ संघर्ष करता है, और डेडलॉक का कारण बनता है।

उत्तर

29

आपके द्वारा वर्णित समस्या डेटाबेस द्वारा संभाली नहीं जाती है, और मेरे अनुभव से पूरी तरह से हाइबरनेट द्वारा संभाला नहीं जाता है।

आपको समस्या होने से बचने के लिए स्पष्ट कदम उठाने होंगे।

हाइबरनेट आपके लिए कुछ काम करता है। पिछले जवाब के मुताबिक, हाइबरनेट यह सुनिश्चित करता है कि एक पृथक फ्लश के भीतर आवेषण, हटाना और अपडेट इस तरह से आदेश दिए जाते हैं जिससे यह सुनिश्चित किया जा सके कि उन्हें एक प्राप्त करने योग्य क्रम में लागू किया जाएगा।AbstractFlushingEventListener कक्षा में performExecutions(EventSource session) देखें:

एक विशेष क्रम में निष्पादित सभी एसक्यूएल (और दूसरे स्तर कैश अद्यतन) ताकि विदेशी कुंजी की कमी का उल्लंघन नहीं किया जा सकता:

  1. आवेषण, क्रम में वे प्रदर्शन किया गया
  2. अपडेट
  3. संग्रह तत्वों का विलोपन संग्रह तत्वों की
  4. निवेशन
  5. हटाता है, ताकि वे

प्रदर्शन किया गया जब अद्वितीय की कमी यह इस आदेश को पता है बहुत महत्वपूर्ण है हो रही है, खासकर यदि आप एक एक-से-कई बच्चे (हटाना वर्ष/नई सम्मिलित) को बदलने के लिए चाहते हैं, लेकिन पुराने और नए बच्चे दोनों ही अद्वितीय बाधाओं को साझा करते हैं (उदाहरण के लिए एक ही ईमेल पता)। इस मामले में आप पुरानी प्रविष्टि को हटाने/डालने के बजाए अपडेट कर सकते हैं, या फिर डालने के बाद ही आप फ्लैश कर सकते हैं। अधिक विस्तृत उदाहरण के लिए आप this article देख सकते हैं।

ध्यान दें कि यह अद्यतनों का क्रम निर्दिष्ट नहीं करता है। हाइबरनेट कोड की जांच करने से मुझे लगता है कि अपडेट ऑर्डर उस क्रम पर निर्भर करेगा जिसमें इकाइयों को दृढ़ता संदर्भ में जोड़ा गया था, ऑर्डर अपडेट किए गए थे। यह आपके कोड में अनुमान लगाया जा सकता है, लेकिन हाइबरनेट कोड पढ़ने से मुझे यह महसूस नहीं हुआ कि मैं उस आदेश पर भरोसा करता हूं।

  1. hibernate.order_updates की स्थापना सच होने के लिए प्रयास करें:

    तीन समाधान मैं के बारे में सोच सकते हैं। इससे डेडलॉक्स से बचने में मदद मिलनी चाहिए जब एक ही टेबल में कई पंक्तियों को अपडेट किया जा रहा है, लेकिन कई तालिकाओं में डेडलॉक्स में मदद नहीं करेगा।

  2. कोई भी अपडेट करने से पहले अपने लेन-देन को PESSIMISTIC_WRITE लॉक करें। आप जिस इकाई का उपयोग करते हैं वह आपकी विशिष्ट स्थिति पर निर्भर करेगा, लेकिन जब तक आप सुनिश्चित करते हैं कि किसी इकाई को डेडलॉक का जोखिम होने पर लगातार चुना जाता है, तो यह शेष लेनदेन को तब तक अवरुद्ध कर देगा जब तक कि लॉक प्राप्त नहीं किया जा सके।
  3. जब वे होते हैं और एक समझदार फैशन में पुनः प्रयास करते हैं तो डेडलॉक्स पकड़ने के लिए अपना कोड लिखें। मृत-लॉक पुनः प्रयास करने वाला घटक वर्तमान लेनदेन सीमा के बाहर स्थित होना चाहिए। ऐसा इसलिए है क्योंकि असफल सत्र बंद होना चाहिए और संबंधित लेन-देन रोल-बैक किया जाना चाहिए। this article में आप एक स्वचालित पुनः प्रयास एओपी पहलू का एक उदाहरण पा सकते हैं।
+1

कृपया मेरी माफी स्वीकार करें कि, अज्ञात कारण से मैंने पहले इस जवाब को याद किया :) मेरा मानना ​​है कि हाइबरनेट के कोड में आपकी परीक्षा का नतीजा वास्तव में अब तक का सबसे भरोसेमंद उत्तर देता है। विशेष रूप से बिंदु 1 और 2 के लिए अच्छे सुझाव –

-1

पहले उदाहरण के बारे में - इस प्रकार की सामग्री डेटाबेस द्वारा संभाली जाती है (लेनदेन अलगाव स्तर और आपके डेटाबेस की लॉकिंग रणनीतियों के बारे में और पढ़ें)। इसे संभालने के कई अलग-अलग तरीके हैं।

हाइबरनेट करने के लिए के रूप में, org.hibernate.event.def.AbstractFlushingEventListener.performExecutions (EventSource) को जावाडोक का कहना है:

सभी एसक्यूएल और दूसरे स्तर कैश अद्यतन निष्पादित, एक विशेष क्रम में इतना है कि विदेशी कुंजी की कमी का उल्लंघन नहीं किया जा सकता:

  1. आवेषण, क्रम में वे प्रदर्शन किया गया
  2. अपडेट संग्रह तत्वों का विलोपन
  3. संग्रह तत्वों की प्रविष्टि
  4. हटाए गए क्रम में,

मुझे लगता है कि यह निष्पादित SQL क्वेरी Hibernate बनाता है का एकमात्र अनुकूलन है। बाकी समस्याओं को डेटाबेस द्वारा संभाला जाता है।

+0

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

+0

संस्थाओं के बीच अद्यतन आदेश है। यह आश्चर्यजनक होगा कि अगर हाइबरनेट में इसका कोई प्रबंधन नहीं हो रहा है और मान लीजिए कि डीबी द्वारा नियंत्रित किया जा सकता है (जो स्पष्ट रूप से अवास्तविक है) –

+0

ओरेकल उदाहरण के लिए किसी भी तरह से डेडलॉक्स को संभालता है "लेनदेन से जुड़े बयान को वापस ले कर स्वचालित रूप से मृतकों का पता लगाता है और हल करता है जो डेडलॉक का पता लगाता है ": http://www.oracle-base.com/articles/misc/deadlocks.php।यह संभवतः जेडीबीसी अपवाद का कारण बनता है, ताकि आप अपवाद को संभालने वाले कोड में कुछ पुनः प्रयास कर सकें। – Potejciak