PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

समवर्ती पहुंच पर तालिका में पंक्तियों के कुछ एनआर को कैसे चिह्नित करें?

संबंधित उत्तर में आप इसका उल्लेख कर रहे हैं:

  • अद्यतन पोस्ट करता है ... सीमा 1

इसका उद्देश्य एक . को लॉक करना है एक समय में पंक्ति। यह एडवाइजरी लॉक के साथ या उसके बिना ठीक काम करता है, क्योंकि डेडलॉक की कोई संभावना नहीं है - जब तक आप एक ही लेन-देन में अधिक पंक्तियों को लॉक करने का प्रयास नहीं करते हैं।

आपका उदाहरण इस मायने में अलग है कि आप एक बार में 3000 पंक्तियों को लॉक करना चाहते हैं . वहाँ है गतिरोध के लिए संभावित, सिवाय इसके कि सभी समवर्ती लेखन संचालन एक ही सुसंगत क्रम में पंक्तियों को लॉक करते हैं। प्रति दस्तावेज़:

<ब्लॉकक्वॉट>

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

इसे अपनी सबक्वेरी में ORDER BY के साथ लागू करें।

UPDATE cargo_item item
SET job_id = 'SOME_UUID', job_ts = now()
FROM  ( 
   SELECT id
   FROM   cargo_item
   WHERE  state='NEW' AND job_id is null 
   ORDER  BY id
   LIMIT  3000
   FOR UPDATE
   ) sub
WHERE  item.id = sub.id;

यह तब तक सुरक्षित और विश्वसनीय है, जब तक सभी लेन-देन उसी क्रम में लॉक प्राप्त करते हैं और ऑर्डरिंग कॉलम के समवर्ती अपडेट की अपेक्षा नहीं की जाती है। (मैनुअल में इस अध्याय के अंत में पीला "सावधानी" बॉक्स पढ़ें।) तो यह आपके मामले में सुरक्षित होना चाहिए, क्योंकि आप id को अपडेट नहीं करने जा रहे हैं। कॉलम।

प्रभावी रूप से एक समय में केवल एक क्लाइंट इस तरह से पंक्तियों में हेरफेर कर सकता है। समवर्ती लेनदेन समान (लॉक) पंक्तियों को लॉक करने का प्रयास करेंगे और पहले लेनदेन के समाप्त होने की प्रतीक्षा करेंगे।

सलाहकार ताले उपयोगी हैं यदि आपके पास कई या बहुत लंबे समय तक चलने वाले समवर्ती लेनदेन हैं (ऐसा नहीं लगता कि आप करते हैं)। केवल कुछ के साथ, केवल उपरोक्त क्वेरी का उपयोग करना और समवर्ती लेनदेन को अपनी बारी की प्रतीक्षा करना समग्र रूप से सस्ता होगा।

सभी एक अद्यतन में

ऐसा लगता है कि समवर्ती पहुंच आपके सेटअप में प्रति समस्या नहीं है। Concurrency आपके वर्तमान समाधान द्वारा बनाई गई एक समस्या है।

इसके बजाय, इसे एक ही UPDATE में करें . n . के बैच असाइन करें प्रत्येक यूयूआईडी के लिए संख्या (उदाहरण में 3000) और सभी को एक साथ अपडेट करें। सबसे तेज़ होना चाहिए।

UPDATE cargo_item c
SET    job_id = u.uuid_col
     , job_ts = now()
FROM  (
   SELECT row_number() OVER () AS rn, uuid_col
   FROM   uuid_tbl WHERE  <some_criteria>  -- or see below
   ) u
JOIN (
   SELECT (row_number() OVER () / 3000) + 1 AS rn, item.id 
   FROM   cargo_item
   WHERE  state = 'NEW' AND job_id IS NULL
   FOR    UPDATE   -- just to be sure
   ) c2 USING (rn)
WHERE  c2.item_id = c.item_id;

प्रमुख बिंदु

  • पूर्णांक विभाजन छोटा हो जाता है। आपको पहली 3000 पंक्तियों के लिए 1, अगली 3000 पंक्तियों के लिए 2 मिलता है। आदि.

  • मैं मनमाने ढंग से पंक्तियों को चुनता हूं, आप ORDER BY लागू कर सकते हैं विंडो में row_number() . के लिए कुछ पंक्तियों को निर्दिष्ट करने के लिए।

  • यदि आपके पास प्रेषण के लिए UUIDs की तालिका नहीं है (uuid_tbl ), एक VALUES . का उपयोग करें उन्हें आपूर्ति करने के लिए अभिव्यक्ति। उदाहरण।

  • आपको 3000 पंक्तियों के बैच मिलते हैं। यदि आपको असाइन करने के लिए 3000 का गुणज नहीं मिलता है, तो अंतिम बैच 3000 से कम होगा।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Java JUnit परीक्षण के लिए एंबेडेड PostgreSQL

  2. असंगत पोस्टग्रेएसक्यूएल दास का पुनर्निर्माण कैसे करें

  3. क्रम में अनुक्रम पीढ़ी

  4. क्या PostgreSQL फंक्शन ट्रांजेक्शनल हैं?

  5. टेक्स्ट प्रतिनिधित्व में हेक्स को दशमलव संख्या में कनवर्ट करें