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

PostgreSQL Upsert सिस्टम कॉलम XMIN, XMAX और अन्य का उपयोग करके सम्मिलित और अद्यतन पंक्तियों में अंतर करता है

मुझे लगता है कि यह एक दिलचस्प सवाल है जो एक गहन उत्तर के योग्य है; कृपया मेरे साथ सहन करें यदि यह थोड़ा लंबा है।

संक्षेप में:आपका अनुमान सही है, और आप निम्न RETURNING का उपयोग कर सकते हैं यह निर्धारित करने के लिए कि क्या पंक्ति डाली गई थी और अपडेट नहीं की गई थी:

RETURNING (xmax = 0) AS inserted

अब विस्तृत विवरण:

जब कोई पंक्ति अपडेट की जाती है, तो PostgreSQL डेटा को संशोधित नहीं करता है, लेकिन एक नया संस्करण बनाता है पंक्ति का; पुराने संस्करण को autovacuum . द्वारा हटा दिया जाएगा जब इसकी अब आवश्यकता नहीं है। पंक्ति के एक संस्करण को tuple . कहा जाता है , इसलिए PostgreSQL में प्रति पंक्ति एक से अधिक टुपल्स हो सकते हैं।

xmax दो अलग-अलग उद्देश्यों को पूरा करता है:

  1. जैसा कि दस्तावेज़ीकरण में कहा गया है, यह उस लेन-देन की लेन-देन आईडी हो सकती है जिसने टपल को हटा दिया (या अपडेट किया गया) ("टपल" "पंक्ति" के लिए एक और शब्द है)। केवल xmin . के बीच लेन-देन आईडी वाले लेन-देन और xmax टपल देख सकते हैं। xmax से कम के लेन-देन आईडी के साथ कोई लेन-देन नहीं होने पर पुराने टपल को सुरक्षित रूप से हटाया जा सकता है ।

  2. xmax पंक्ति ताले . को स्टोर करने के लिए भी प्रयोग किया जाता है . PostgreSQL में, लॉक टेबल में रो लॉक को स्टोर नहीं किया जाता है, बल्कि लॉक टेबल के ओवरफ्लो से बचने के लिए टपल में स्टोर किया जाता है।
    यदि केवल एक ट्रांजैक्शन में रो पर लॉक है, तो xmax लॉकिंग लेनदेन की लेनदेन आईडी होगी। यदि एक से अधिक लेन-देन की पंक्ति पर लॉक है, तो xmax एक तथाकथित मल्टीएक्सएक्ट . की संख्या शामिल है , जो एक डेटा संरचना है जिसमें बदले में लॉकिंग लेनदेन की लेनदेन आईडी शामिल होती है।

xmax . का दस्तावेज़ीकरण पूर्ण नहीं है, क्योंकि इस फ़ील्ड का सटीक अर्थ एक कार्यान्वयन विवरण माना जाता है और इसे t_infomask जाने बिना नहीं समझा जा सकता है टपल का, जो तुरंत SQL के माध्यम से दिखाई नहीं देता है।

आप contrib मॉड्यूल pageinspect स्थापित कर सकते हैं इसे और टपल के अन्य क्षेत्रों को देखने के लिए।

मैंने आपका उदाहरण चलाया, और जब मैं heap_page_items का उपयोग करता हूं तो मुझे यही दिखाई देता है विवरण की जांच करने के लिए कार्य (मेरे मामले में लेनदेन आईडी नंबर निश्चित रूप से भिन्न हैं):

SELECT *, ctid, xmin, xmax FROM t;

┌───┬────┬───────┬────────┬────────┐
│ i │ x  │ ctid  │  xmin  │  xmax  │
├───┼────┼───────┼────────┼────────┤
│ 1 │ 11 │ (0,2) │ 102508 │ 102508 │
│ 2 │ 22 │ (0,3) │ 102508 │      0 │
└───┴────┴───────┴────────┴────────┘
(2 rows)

SELECT lp, lp_off, t_xmin, t_xmax, t_ctid,
       to_hex(t_infomask) AS t_infomask, to_hex(t_infomask2) AS t_infomask2
FROM heap_page_items(get_raw_page('laurenz.t', 0));

┌────┬────────┬────────┬────────┬────────┬────────────┬─────────────┐
│ lp │ lp_off │ t_xmin │ t_xmax │ t_ctid │ t_infomask │ t_infomask2 │
├────┼────────┼────────┼────────┼────────┼────────────┼─────────────┤
│  1 │   8160 │ 102507 │ 102508 │ (0,2)  │ 500        │ 4002        │
│  2 │   8128 │ 102508 │ 102508 │ (0,2)  │ 2190       │ 8002        │
│  3 │   8096 │ 102508 │      0 │ (0,3)  │ 900        │ 2           │
└────┴────────┴────────┴────────┴────────┴────────────┴─────────────┘
(3 rows)

t_infomask . का अर्थ और t_infomask2 src/include/access/htup_details.h . में पाया जा सकता है . lp_off पृष्ठ में टपल डेटा की ऑफसेट है, और t_ctid वर्तमान टपल आईडी है जिसमें पेज नंबर और पेज के भीतर एक टुपल नंबर होता है। चूंकि तालिका नई बनाई गई थी, सभी डेटा पृष्ठ 0 में हैं।

मुझे heap_page_items . द्वारा लौटाई गई तीन पंक्तियों पर चर्चा करने दें ।

  1. लाइन पॉइंटर . पर (lp ) 1 हम पुराने, अद्यतन टपल पाते हैं। इसमें मूल रूप से ctid = (0,1) था , लेकिन अद्यतन के दौरान वर्तमान संस्करण की टपल आईडी को शामिल करने के लिए इसे संशोधित किया गया। टुपल 102507 लेनदेन द्वारा बनाया गया था और लेनदेन 102508 द्वारा अमान्य कर दिया गया था (वह लेनदेन जिसने INSERT ... ON CONFLICT जारी किया था। ) VACUUM . के दौरान वसीयत हटा दी जाएगी यह टपल अब और दिखाई नहीं दे रहा है ।

    t_infomask दिखाता है कि दोनों xmin और xmax प्रतिबद्ध लेन-देन से संबंधित हैं और परिणामस्वरूप दिखाते हैं कि टुपल्स कब बनाए और हटाए गए थे। t_infomask2 दिखाता है कि टपल को एक HOT (हीप ओनली टपल . के साथ अपडेट किया गया था ) अद्यतन, जिसका अर्थ है कि अद्यतन टपल मूल टपल के समान पृष्ठ में है और कोई अनुक्रमित स्तंभ संशोधित नहीं किया गया था (देखें src/backend/access/heap/README.HOT )।

  2. लाइन पॉइंटर 2 पर हम नया, अपडेटेड टपल देखते हैं जो INSERT ... ON CONFLICT ट्रांजेक्शन द्वारा बनाया गया था। (लेनदेन 102508)।

    t_infomask दिखाता है कि यह टपल एक अपडेट का परिणाम है, xmin मान्य है, और xmax एक KEY SHARE शामिल है पंक्ति लॉक (जो अब प्रासंगिक नहीं है क्योंकि लेनदेन पूरा हो गया है)। यह रो लॉक INSERT ... ON CONFLICT . के दौरान लिया गया था प्रसंस्करण। t_infomask2 दिखाता है कि यह एक हॉट टपल है।

  3. लाइन पॉइंटर 3 पर हम नई डाली गई पंक्ति देखते हैं।

    t_infomask दिखाता है कि xmin मान्य है और xmax अमान्य है। xmax 0 पर सेट है क्योंकि यह मान हमेशा नए डाले गए टुपल्स के लिए उपयोग किया जाता है।

तो गैर-शून्य xmax अद्यतन पंक्ति की एक पंक्ति लॉक के कारण एक कार्यान्वयन आर्टिफैक्ट है। यह बोधगम्य है कि INSERT ... ON CONFLICT एक दिन फिर से लागू किया जाता है ताकि यह व्यवहार बदल जाए, लेकिन मुझे लगता है कि इसकी संभावना नहीं है।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Libpq का उपयोग करके iPhone ऐप को PostgreSQL से कनेक्ट करें

  2. PostgreSQL चयन क्वेरी में कॉलम की अधिकतम संख्या क्या है

  3. NoSuchMethodError प्राप्त करना:javax.persistence.Table.indexes() जेपीए क्वेरी करते समय

  4. PostgreSQL में परिकलित / परिकलित / आभासी / व्युत्पन्न कॉलम

  5. अपने डेटाबेस को PostgreSQL संस्करण 10 में अपग्रेड करना - आपको क्या पता होना चाहिए