TL;DR:क्रमागत संघर्षों का पता लगाने में Pg 9.1 में नाटकीय रूप से सुधार हुआ है, इसलिए अपग्रेड करें।
आपके विवरण से यह पता लगाना मुश्किल है कि वास्तविक SQL क्या है और आप रोलबैक प्राप्त करने की अपेक्षा क्यों करते हैं। ऐसा लगता है कि आपने गंभीरता से क्रमबद्ध अलगाव को गलत समझा है, शायद यह सोचकर कि यह पूरी तरह से सभी विधेय का परीक्षण करता है, जो यह नहीं करता है, विशेष रूप से Pg 8.4 में नहीं।
SERIALIZABLE
पूरी तरह से गारंटी नहीं देता है कि लेनदेन निष्पादित होते हैं जैसे कि वे श्रृंखला में चलाए गए थे - ऐसा करने से प्रदर्शन के दृष्टिकोण से निषिद्ध रूप से महंगा होगा यदि यह संभव था। यह केवल सीमित जाँच प्रदान करता है। वास्तव में क्या चेक किया गया है और डेटाबेस से डेटाबेस और संस्करण से संस्करण में कैसे भिन्न होता है, इसलिए आपको अपने डेटाबेस के संस्करण के लिए दस्तावेज़ पढ़ने की आवश्यकता है।
विसंगतियाँ संभव हैं, जहाँ दो लेन-देन SERIALIZABLE
. में निष्पादित हो रहे हैं मोड एक अलग परिणाम उत्पन्न करता है यदि उन लेनदेन को वास्तव में श्रृंखला में निष्पादित किया जाता है।
अधिक जानने के लिए Pg में लेन-देन अलगाव पर दस्तावेज़ पढ़ें। ध्यान दें कि SERIALIZABLE
Pg 9.1 में व्यवहार में नाटकीय रूप से बदलाव आया है, इसलिए अपने Pg संस्करण के लिए उपयुक्त मैनुअल के संस्करण को पढ़ना सुनिश्चित करें। यह रहा 8.4 वर्शन
. विशेष रूप से 13.2.2.1 पढ़ें। सीरियलाइज़ेबल आइसोलेशन बनाम ट्रू सीरियलाइज़ेबिलिटी
. अब इसकी तुलना बहुत बेहतर प्रेडिकेट लॉकिंग आधारित सीरियलाइज़ेशन सपोर्ट से करें जिसका वर्णन इस में किया गया है पृष्ठ 9.1 दस्तावेज़
।
ऐसा लगता है कि आप इस छद्म कोड की तरह तर्क करने की कोशिश कर रहे हैं:
count = query("SELECT count(*) FROM the_table");
if (count < threshold):
query("INSERT INTO the_table (...) VALUES (...)");
यदि ऐसा है, तो यह समवर्ती रूप से निष्पादित होने पर पीजी 8.4 में काम नहीं करेगा - यह ऊपर दिए गए दस्तावेज़ीकरण में उपयोग किए गए विसंगति उदाहरण के समान ही है। आश्चर्यजनक रूप से यह वास्तव में पृष्ठ 9.1 पर काम करता है; मुझे उम्मीद नहीं थी कि 9.1 की प्रेडिकेट लॉकिंग भी समुच्चय के उपयोग को पकड़ पाएगी।
आप लिखते हैं कि:
लेकिन 8.4 यह पता नहीं लगाएगा कि दो लेन-देन अन्योन्याश्रित हैं, कुछ ऐसा जिसे आप दो psql
का उपयोग करके तुच्छ रूप से साबित कर सकते हैं इसका परीक्षण करने के लिए सत्र। यह केवल 9.1 में पेश की गई सच्ची-क्रमिकता सामग्री के साथ है कि यह काम करेगा - और स्पष्ट रूप से, मुझे आश्चर्य हुआ कि यह 9.1 में काम करता है।
यदि आप Pg 8.4 में अधिकतम पंक्ति गणना लागू करने जैसा कुछ करना चाहते हैं, तो आपको LOCK
टेबल
समवर्ती INSERT
. को रोकने के लिए s, मैन्युअल रूप से या ट्रिगर फ़ंक्शन . इसे ट्रिगर में करने के लिए स्वाभाविक रूप से लॉक प्रमोशन की आवश्यकता होगी और इस प्रकार अक्सर गतिरोध होगा, लेकिन सफलतापूर्वक काम करेगा। यह उस एप्लिकेशन में बेहतर है जहां आप LOCK TABLE my_table IN EXCLUSIVE MODE
जारी कर सकते हैं। SELECT
. प्राप्त करने से पहले तालिका से आईएनजी, इसलिए इसमें पहले से ही उच्चतम लॉक मोड है जिसकी उसे टेबल पर आवश्यकता होगी और इस प्रकार डेडलॉक-प्रवण लॉक प्रचार की आवश्यकता नहीं होनी चाहिए। EXCLUSIVE
लॉक मोड उपयुक्त है क्योंकि यह SELECT
. की अनुमति देता है s लेकिन और कुछ नहीं।
यहां दो psql सत्रों में इसका परीक्षण करने का तरीका बताया गया है:
SESSION 1 SESSION 2
create table ser_test( x text );
BEGIN TRANSACTION
ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION
ISOLATION LEVEL SERIALIZABLE;
SELECT count(*) FROM ser_test ;
SELECT count(*) FROM ser_test ;
INSERT INTO ser_test(x) VALUES ('bob');
INSERT INTO ser_test(x) VALUES ('bob');
COMMIT;
COMMIT;
जब Pg 9.1 पर चलाया जाता है, तो st commits succeeds then the second
COMMIT` इसके साथ विफल रहता है:
regress=# COMMIT;
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.
लेकिन जब 8.4 पर चलाया जाता है तो दोनों कमिट सफल होते हैं, क्योंकि 8.4 में 9.1 में जोड़े गए क्रमिकता के लिए सभी विधेय लॉकिंग कोड नहीं थे।