2016-12-19 18 views
6

Postgres साथ JDBC पर काम करते समय ...कैसे अद्यतन गतिरोध

Isolationlevel = "प्रतिबद्ध पढ़ें"

मैं एक बहु-क्रम वातावरण में एक ही गतिरोध हो गया, जब मैं कुछ के बाद तालिका को अद्यतन करने की कोशिश की बचें संचालन। तो मैं नीचे के रूप में

ps = con.prepareStatement("UPDATE TableA SET column1=column1-? WHERE column2=? and column3=?;" 
          + "UPDATE TableA SET column1=column1+? WHERE column2=? and column3=?;"); 

यहाँ दिखाए गए त्रुटि

2016-12-19 12:25:44 IST STATEMENT: UPDATE TableA SET column1=column1+$1 WHERE column2=$2 and column3=$3 
2016-12-19 12:25:44 IST FATAL: connection to client lost 
2016-12-19 12:25:45 IST ERROR: deadlock detected 
2016-12-19 12:25:45 IST DETAIL: Process 8524 waits for ShareLock on transaction 84942; blocked by process 12520. 
    Process 12520 waits for ShareLock on transaction 84940; blocked by process 20892. 
    Process 20892 waits for ExclusiveLock on tuple (1,5) of relation 25911 of database 24736; blocked by process 8524. 
    Process 8524: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3 
    Process 12520: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3 
    Process 20892: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3 
2016-12-19 12:25:45 IST HINT: See server log for query details. 
2016-12-19 12:25:45 IST CONTEXT: while locking tuple (1,12) in relation "TableA" 
2016-12-19 12:25:45 IST STATEMENT: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3 
2016-12-19 12:25:45 IST LOG: could not send data to client: No connection could be made because the target machine actively refused it. 

के लिए PostgreSQL लॉग इस बहु-क्रम वातावरण में, मैं TableA की पंक्तियों उम्मीद कर रहा था 2 बयानों के लिए लॉक हो जाए और कर रहे हैं कई प्रश्न उपयोग करने की कोशिश डेडलॉक से बचें।

मैं देख रहा हूँ समान परिदृश्य Postgres Docs

में विस्तार से बताया मैं गतिरोध के इस प्रकार से बचने के लिए कोई भी तरीका नहीं पा सके। किसी भी मदद की सराहना की है। धन्यवाद

पीएस: Autocommit पहले से ही गलत सेट किया गया है और एकल अद्यतन क्वेरी के साथ तैयार स्टेटमेंट का उपयोग करने का प्रयास किया है।

कई के बारे में प्रश्नों ->Multiple queries in one Preparedstatement और this से पता चलता नहीं करता है कि postgres किसी भी अतिरिक्त विन्यास की जरूरत है।

+1

अपडेट पूरे तालिका को लॉक नहीं करते हैं, केवल प्रश्न में पंक्ति। आपके द्वारा लिंक किए गए दस्तावेज़ों से: 'डेडलॉक्स के खिलाफ सबसे अच्छा बचाव आम तौर पर यह सुनिश्चित करके उनसे बचने के लिए होता है कि डेटाबेस का उपयोग करने वाले सभी एप्लिकेशन लगातार ऑर्डर में एकाधिक ऑब्जेक्ट्स पर लॉक प्राप्त करते हैं।' –

+0

आप दो 'अद्यतन' कथन कैसे तैयार करते हैं? .. –

+0

क्षमा करें, मेरी गलती @ निकबर्नेस। मेरा मतलब केवल पंक्तियां थीं। मुझे उस तालिका में दो पंक्तियों को एक बहुप्रचारित वातावरण में अपडेट करने की आवश्यकता है। मैं ऐसी स्थिति में डेडलॉक कैसे रोक सकता हूं और कार्यक्षमता प्राप्त कर सकता हूं? – Vamsidhar

उत्तर

5

जैसा कि @ निक बार्न्स ने साझा किए गए लिंक से टिप्पणी में उद्धृत किया था।

गतिरोध के खिलाफ सबसे अच्छा बचाव उन्हें निश्चित होने से बचने के लिए आम तौर पर है कि एक संगत आदेश में से अधिक ऑब्जेक्ट पर एक डेटाबेस अधिग्रहण ताले का उपयोग कर सभी आवेदनों।

विशेष रूप से उल्लेख किए गए डेडलॉक्स अपडेट करने के लिए, अपडेट का क्रम डेडलॉक की ओर जाता है।

उदाहरण:

UPDATE Table SET ... WHERE id= 1; 
UPDATE Table SET ... WHERE id= 2; 

और

UPDATE Table SET ... WHERE id= 2; 
UPDATE Table SET ... WHERE id= 1; 

सामान्य समाधान आदेश अपडेट आईडी के आधार पर की जाती है। यह लगातार आदेश का मतलब है।

मुझे समझ में नहीं आया कि जब तक मैं इस डेडलॉक से संघर्ष नहीं करता।

1

पोस्टग्रेएसक्यूएल में मेरे अनुभव डेडलॉक द्वारा "वास्तविक जीवन" में सबसे अधिक संभावना होती है जब आप 2 लंबे समय तक चल रहे लेनदेन में अपडेट "पार" करते हैं। (स्पष्टीकरण निम्नानुसार है)। और पीजी पर डेडलॉक अनुकरण करना भी मुश्किल है। यहाँ एक उदाहरण है - http://postgresql.freeideas.cz/simulate-deadlock-postgresql/ तो शास्त्रीय गतिरोध का अर्थ है:

  • आप शुरू लेनदेन 1 + पंक्ति 1. अपने प्रक्रिया जारी है लेकिन लेन-देन 1 अभी भी खोल दिया है और नहीं के लिए प्रतिबद्ध है पर अद्यतन करते हैं।
  • फिर आप पंक्ति 2 पर लेनदेन 2 + अपडेट शुरू करते हैं। प्रक्रिया जारी है लेकिन लेनदेन 2 अभी भी खोला गया है और नहीं किया गया है।
  • अब आप लेनदेन 1 से पंक्ति 2 को अपडेट करने का प्रयास करते हैं जो इस ऑपरेशन को प्रतीक्षा करने का कारण बनता है।
  • अब आप लेनदेन 2 से पंक्ति 1 को अपडेट करने का प्रयास करते हैं - इस समय पीजी डेडलॉक की रिपोर्ट करता है और इस लेनदेन को समाप्त करता है।

तो मैं आपको जितनी जल्दी हो सके लेनदेन करने की सलाह देता हूं।

+1

उत्तर के लिए धन्यवाद। लेकिन वास्तविक जीवन में हम autoCommit नहीं कर सकते हैं। दूसरे अपडेट या बाद में विफल होने पर मुझे रोलबैक की आवश्यकता है। – Vamsidhar

+1

मैं इसे समझता हूं और मैंने "autoCommit" के बारे में कुछ भी नहीं कहा। लेकिन यदि आपके पास बहुत अधिक थ्रेडेड वातावरण है और आप अपेक्षाकृत लंबे समय तक लेनदेन खोले हैं तो डेडलॉक्स होने की संभावना बहुत अधिक है। लेनदेन काम करता है। – JosMac

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