2017-02-17 4 views
6

मेरी समझ PostgreSQL में नज़र रखता है किसी तरह का उपयोग करने वहाँ serializable अलगाव स्तर में परस्पर विरोध होने पर अनुमान लगाना। समसामयिक लेनदेन में एक ही संसाधन को संशोधित करने के बारे में कई उदाहरण हैं, और क्रमिक लेनदेन महान काम करता है। लेकिन मैं एक और तरीके से समवर्ती मुद्दे का परीक्षण करना चाहता हूं।PostgreSQL serializable लेनदेन क्यों इसे संघर्ष के रूप में सोचता है?

मैं अपने स्वयं के खाते की शेष राशि को संशोधित 2 उपयोगकर्ताओं परीक्षण करने का निर्णय, और इच्छा PostgreSQL बहुत चालाक संघर्ष के रूप में यह पता नहीं लगा है, लेकिन परिणाम नहीं है कि मैं क्या चाहता हूँ।

नीचे मेरी मेज है, वहाँ 4 खातों के अंतर्गत आता है 2 उपयोगकर्ताओं रहे हैं, प्रत्येक उपयोगकर्ता एक चेकिंग खाता है और एक बचत खाता है।

create table accounts (
    id serial primary key, 
    user_id int, 
    type varchar, 
    balance numeric 
); 

insert into accounts (user_id, type, balance) values 
    (1, 'checking', 1000), 
    (1, 'saving', 1000), 
    (2, 'checking', 1000), 
    (2, 'saving', 1000); 

तालिका डेटा इस तरह है:

id | user_id | type | balance 
----+---------+----------+--------- 
    1 |  1 | checking | 1000 
    2 |  1 | saving | 1000 
    3 |  2 | checking | 1000 
    4 |  2 | saving | 1000 

अब मैं 2 उपयोगकर्ताओं के लिए 2 समवर्ती लेनदेन चलाते हैं। प्रत्येक लेनदेन में, मैं कुछ पैसे के साथ चेकिंग खाता कम करता हूं, और उस उपयोगकर्ता की कुल शेष राशि की जांच करता हूं। यदि यह 1000 से अधिक है, तो प्रतिबद्ध करें, अन्यथा रोलबैक।

1 के उपयोगकर्ता उदाहरण:

begin; 

-- Reduce checking account for user 1 
update accounts set balance = balance - 200 where user_id = 1 and type = 'checking'; 

-- Make sure user 1's total balance > 1000, then commit 
select sum(balance) from accounts where user_id = 1; 

commit; 

उपयोगकर्ता 2, एक ही है user_id = 2where में छोड़कर:

begin; 
update accounts set balance = balance - 200 where user_id = 2 and type = 'checking'; 
select sum(balance) from accounts where user_id = 2; 
commit; 

मैं पहली बार 1 के उपयोगकर्ता लेन-देन के लिए प्रतिबद्ध है, यह कोई संदेह नहीं है के साथ सफलता। जब मैं उपयोगकर्ता 2 के लेनदेन को प्रतिबद्ध करता हूं, तो यह विफल हो जाता है।

ERROR: could not serialize access due to read/write dependencies among transactions 
DETAIL: Reason code: Canceled on identification as a pivot, during commit attempt. 
HINT: The transaction might succeed if retried. 

मेरे प्रश्न हैं:

  1. क्यों PostgreSQL सोचता है कि यह 2 लेन-देन कर रहे हैं संघर्ष? मैंने सभी SQL के लिए user_id स्थिति जोड़ा, और user_id को संशोधित नहीं करता है, लेकिन इन सभी का कोई प्रभाव नहीं है।
  2. कि serializable लेनदेन मतलब यह है समवर्ती लेनदेन एक ही मेज पर हुआ की अनुमति नहीं है, भले ही उनकी पढ़ें/लिखें कोई विवाद नहीं है?
  3. मैं संचालन जो बहुत अक्सर होता लिए serializable लेनदेन प्रयोग से बचना चाहिए प्रति उपयोगकर्ता कुछ बहुत आम है क्या?
+0

आप पोस्टग्रेस मेलिंग सूची –

उत्तर

5

आप निम्न सूचकांक के साथ इस समस्या को ठीक कर सकते हैं:

SET enable_seqscan=off; 
:

CREATE INDEX accounts_user_idx ON accounts(user_id); 

के बाद से अपने उदाहरण तालिका में तो कुछ डेटा देखते हैं, तो आप एक सूचकांक स्कैन का उपयोग करने के PostgreSQL बताने के लिए होगा

अब आपका उदाहरण काम करेगा!

यदि यह काला जादू की तरह लगता है, तो अपने SELECT और UPDATE कथनों की क्वेरी निष्पादन योजनाओं पर नज़र डालें।

सूचकांक के बिना दोनों तालिका पर अनुक्रमिक स्कैन का उपयोग करेंगे, जिससे तालिका तालिका में सभी पंक्तियां पढ़ती हैं। तो दोनों लेनदेन पूरी तालिका पर SIReadLock के साथ समाप्त हो जाएंगे।

यह क्रमबद्धता विफलता को ट्रिगर करता है।

+0

तो मुख्य बिंदु पूर्ण तालिका स्कैन से बचने के लिए है, और तालिका डेटा बहुत कम है, तो सूचकांक ट्रिगर नहीं किया गया है, क्या मेरी समझ सही है? – darkbaby123

+0

यह बिल्कुल सही है। –

-2

मेरे ज्ञान के लिए serializable अलगाव का उच्चतम स्तर है, इसलिए संक्षेप में निम्नतम स्तर है। लेनदेन शून्य के साथ एक दूसरे के बाद होता है।

+0

पर यह पूछना चाहेंगे क्यों PostgreSQL सोचता है कि यह 2 लेनदेन संघर्ष हैं? मैंने सभी SQL के लिए user_id स्थिति जोड़ा, और user_id को संशोधित नहीं करता है, लेकिन इन सभी का कोई प्रभाव नहीं है। -> यह सुनिश्चित नहीं है कि आपके पास यह संघर्ष दोस्त क्यों है, शायद जब यह रिकॉर्ड की तलाश में है क्योंकि उसके पास 'चेकिंग' प्रकार का एक सामान्य क्षेत्र एक कारण हो सकता है। क्या आपने 'बचत' के साथ एक कोशिश की और एक 'चेकिंग' – sivalingam

+0

के साथ मैंने कोशिश की, अभी भी संघर्ष। असल में यह तब भी संघर्ष होता है जब सभी स्थितियों को 'user_id = x'' में कम कर दिया जाता है। – darkbaby123

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