मुझे लगता है कि यह एक दिलचस्प सवाल है जो एक गहन उत्तर के योग्य है; कृपया मेरे साथ सहन करें यदि यह थोड़ा लंबा है।
संक्षेप में:आपका अनुमान सही है, और आप निम्न 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
अमान्य है।xmax
0 पर सेट है क्योंकि यह मान हमेशा नए डाले गए टुपल्स के लिए उपयोग किया जाता है।
तो गैर-शून्य xmax
अद्यतन पंक्ति की एक पंक्ति लॉक के कारण एक कार्यान्वयन आर्टिफैक्ट है। यह बोधगम्य है कि INSERT ... ON CONFLICT
एक दिन फिर से लागू किया जाता है ताकि यह व्यवहार बदल जाए, लेकिन मुझे लगता है कि इसकी संभावना नहीं है।