जब भी आप SERIALIZABLE
. का अनुरोध करते हैं अलगाव डीबी प्रश्नों के समवर्ती सेट बनाने का प्रयास करेगा क्रमिक रूप से निष्पादित प्रतीत होता है उनके द्वारा उत्पादित परिणामों के संदर्भ में। यह हमेशा संभव नहीं होता है, उदा। जब दो लेन-देन में परस्पर निर्भरता होती है। इस मामले में, PostgreSQL एक लेन-देन को निरस्त कर देगा क्रमांकन विफलता त्रुटि के साथ, आपको बता रहा है कि आपको इसे पुनः प्रयास करना चाहिए।
कोड जो SERIALIZABLE
. का उपयोग करता है लेन-देन के पुन:प्रयास के लिए हमेशा तैयार रहना चाहिए। इसे SQLSTATE
की जांच करनी चाहिए और, क्रमांकन विफलताओं के लिए, लेन-देन दोहराएं।
देखें लेन-देन अलगाव दस्तावेज़ ।
इस मामले में, मुझे लगता है कि आपकी मुख्य गलतफहमी यह हो सकती है:
क्योंकि यह ऐसा कुछ नहीं है, यह एक INSERT ... SELECT
. है जो vo_business.repositoryoperation
. को छूता है पढ़ने और लिखने दोनों के लिए। यह किसी अन्य लेन-देन के साथ संभावित निर्भरता बनाने के लिए पर्याप्त है जो ऐसा ही करता है, या वह जो किसी अन्य तरीके से तालिका को पढ़ता और लिखता है।
इसके अतिरिक्त, क्रमिक अलगाव कोड कुछ परिस्थितियों में दक्षता कारणों से ब्लॉक-स्तरीय निर्भरता जानकारी रखने में डी-जेनरेट कर सकता है। तो यह जरूरी नहीं कि एक ही पंक्तियों को छूने वाला लेन-देन हो, केवल एक ही स्टोरेज ब्लॉक, विशेष रूप से लोड के तहत।
यदि यह सुनिश्चित नहीं है कि यह सुरक्षित है, तो PostgreSQL एक क्रमबद्ध लेनदेन को रद्द करना पसंद करेगा। प्रूफ सिस्टम की सीमाएँ हैं। तो यह भी संभव है कि आपने अभी-अभी कोई ऐसा मामला ढूंढा हो जो इसे मूर्ख बनाता हो।
निश्चित रूप से जानने के लिए मुझे दोनों लेन-देन को साथ-साथ देखना होगा, लेकिन यहां एक सबूत है जो insert ... select
दिखा रहा है स्वयं के साथ संघर्ष कर सकता है। तीन खोलें psql
सत्र और रन:
session0: CREATE TABLE serialdemo(x integer, y integer);
session0: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
session0: LOCK TABLE serialdemo IN ACCESS EXCLUSIVE MODE;
session1: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
session2: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
session1: INSERT INTO serialdemo (x, y)
SELECT 1, 2
WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);
session2: INSERT INTO serialdemo (x, y)
SELECT 1, 2
WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);
session0: ROLLBACK;
session1: COMMIT;
session2: COMMIT;
सत्र 1 ठीक करेगा। session2 इसके साथ विफल हो जाएगा:
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.
यह आपके मामले के समान क्रमांकन विफलता नहीं है, और यह साबित नहीं करता है कि आपका कथन एक दूसरे के साथ विरोध कर सकते हैं, लेकिन यह दर्शाता है कि एक insert ... select
उतना परमाणु नहीं है जितना आपने सोचा था।