मुझे लगता है कि यह एक दिलचस्प सवाल है जो एक गहन उत्तर के योग्य है; कृपया मेरे साथ सहन करें यदि यह थोड़ा लंबा है।
संक्षेप में:आपका अनुमान सही है, और आप निम्न RETURNING का उपयोग कर सकते हैं यह निर्धारित करने के लिए कि क्या पंक्ति डाली गई थी और अपडेट नहीं की गई थी:
RETURNING (xmax = 0) AS inserted
अब विस्तृत विवरण:
जब कोई पंक्ति अपडेट की जाती है, तो PostgreSQL डेटा को संशोधित नहीं करता है, लेकिन एक नया संस्करण बनाता है पंक्ति का; पुराने संस्करण को autovacuum . द्वारा हटा दिया जाएगा जब इसकी अब आवश्यकता नहीं है। पंक्ति के एक संस्करण को tuple . कहा जाता है , इसलिए PostgreSQL में प्रति पंक्ति एक से अधिक टुपल्स हो सकते हैं।
xmax दो अलग-अलग उद्देश्यों को पूरा करता है:
-
जैसा कि दस्तावेज़ीकरण में कहा गया है, यह उस लेन-देन की लेन-देन आईडी हो सकती है जिसने टपल को हटा दिया (या अपडेट किया गया) ("टपल" "पंक्ति" के लिए एक और शब्द है)। केवल
xmin. के बीच लेन-देन आईडी वाले लेन-देन औरxmaxटपल देख सकते हैं।xmaxसे कम के लेन-देन आईडी के साथ कोई लेन-देन नहीं होने पर पुराने टपल को सुरक्षित रूप से हटाया जा सकता है । -
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 . द्वारा लौटाई गई तीन पंक्तियों पर चर्चा करने दें ।
-
लाइन पॉइंटर . पर (
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 पर हम नया, अपडेटेड टपल देखते हैं जो
INSERT ... ON CONFLICTट्रांजेक्शन द्वारा बनाया गया था। (लेनदेन 102508)।t_infomaskदिखाता है कि यह टपल एक अपडेट का परिणाम है,xminमान्य है, औरxmaxएकKEY SHAREशामिल है पंक्ति लॉक (जो अब प्रासंगिक नहीं है क्योंकि लेनदेन पूरा हो गया है)। यह रो लॉकINSERT ... ON CONFLICT. के दौरान लिया गया था प्रसंस्करण।t_infomask2दिखाता है कि यह एक हॉट टपल है। -
लाइन पॉइंटर 3 पर हम नई डाली गई पंक्ति देखते हैं।
t_infomaskदिखाता है किxminमान्य है औरxmaxअमान्य है।xmax0 पर सेट है क्योंकि यह मान हमेशा नए डाले गए टुपल्स के लिए उपयोग किया जाता है।
तो गैर-शून्य xmax अद्यतन पंक्ति की एक पंक्ति लॉक के कारण एक कार्यान्वयन आर्टिफैक्ट है। यह बोधगम्य है कि INSERT ... ON CONFLICT एक दिन फिर से लागू किया जाता है ताकि यह व्यवहार बदल जाए, लेकिन मुझे लगता है कि इसकी संभावना नहीं है।