PostgreSQL डेटाबेस तालिका का अंतिम संशोधन दिनांक प्राप्त करना


35

मैं कोशिश कर रहा हूं कि जब मेरी फ़ाइल संशोधन तिथि की जांच करके मेरी तालिका संशोधित हो जाए, जैसा कि इस उत्तर में वर्णित है । लेकिन परिणाम हमेशा सही नहीं होता है। अपनी तालिका अपडेट करने के बाद फ़ाइल संशोधन तिथि कई मिनटों में अपडेट हो जाती है। क्या यह सही व्यवहार है? क्या PostgreSQL कुछ कैश में टेबल संशोधनों को स्टोर करता है और फिर इसे हार्ड ड्राइव में फ्लश करता है?

तो, मुझे तालिका की सही अंतिम संशोधन तिथि कैसे मिल सकती है (मान लें कि ऑटो वैक्यूम संशोधन ठीक हैं)?

मैं लिनक्स Centos 6.2 x64 के तहत PostgreSQL 9.2 का उपयोग करता हूं।


4
मुझे नहीं लगता कि फ़ाइल संशोधन समय विश्वसनीय है। यह ऑटोवैक्यूम के कारण भी बदल सकता है। एकमात्र विश्वसनीय तरीका अपनी तालिका में एक संशोधन टाइमस्टैम्प को संग्रहीत करना है, जो एक ट्रिगर द्वारा बनाए रखा गया है।
a_horse_with_no_name 14

एक विचार यह होगा कि लेन फ़ाइलों में संग्रहीत जानकारी डेटा फ़ाइलों को कुछ (कम या अधिक) लेनदेन करने के बाद के समय के लिए लिखा जाता है। यदि आप चाहें, तो आप इसे कैश कह सकते हैं :) अन्यथा, मैं दूसरा कहता हूं @a_horse_with_no_name ने कहा।
dezso

जवाबों:


35

तालिका के अंतिम संशोधित समय का कोई विश्वसनीय, आधिकारिक रिकॉर्ड नहीं है। कई कारणों से रफ़िलीनोड का उपयोग करना गलत है:

  • राइट्स को शुरू में राइट-हेड लॉग (वाल) में दर्ज किया जाता है, फिर lazily to heap (टेबल फाइलें)। एक बार रिकॉर्ड होने के बाद, Pg इसे ढेर में लिखने के लिए जल्दी नहीं करता है, और यह अगले सिस्टम चेकपॉइंट तक भी नहीं लिखा जा सकता है;

  • बड़ी तालिकाओं में कई कांटे होते हैं, आपको सभी कांटों की जांच करनी होगी और नवीनतम टाइमस्टैम्प चुनना होगा;

  • एक साधारण SELECTसंकेत-बिट सेटिंग के कारण अंतर्निहित तालिका में लेखन गतिविधि उत्पन्न कर सकता है;

  • ऑटोवेकम और अन्य रखरखाव जो उपयोगकर्ता को दिखाई देने वाले डेटा को नहीं बदलते हैं, अभी भी संबंध फाइलों को संशोधित करता है;

  • कुछ ऑपरेशन, जैसे vaccum full, रिलफेनोड को बदल देंगे। यह वह जगह नहीं हो सकती है जहां आप उम्मीद करते हैं कि आप उचित ताला न लगाकर समवर्ती रूप से देखने की कोशिश कर रहे हैं।

कुछ विकल्प

आप विश्वसनीयता की जरूरत नहीं है, तो आप संभवतः में जानकारी का उपयोग कर सकते हैं pg_stat_databaseऔर pg_stat_all_tables। ये आपको अंतिम आँकड़े रीसेट करने का समय दे सकते हैं, और अंतिम आँकड़े रीसेट होने के बाद से गतिविधि आँकड़े । यह आपको नहीं बताता है कि सबसे हाल की गतिविधि कब थी, केवल यह कि यह आखिरी आँकड़े रीसेट के बाद से था, और उस आँकड़े के रीसेट होने से पहले क्या हुआ, इसके बारे में कोई जानकारी नहीं है। तो यह सीमित है, लेकिन यह पहले से ही वहां है।

इसे मज़बूती से करने का एक विकल्प यह है कि प्रत्येक तालिका के लिए अंतिम-संशोधित समय वाली तालिका को अद्यतन करने के लिए ट्रिगर का उपयोग किया जाए। ध्यान रखें कि ऐसा करने से तालिका के सभी लेखन क्रमबद्ध हो जाएंगे , संक्षिप्तता को नष्ट कर देंगे । यह हर लेन-देन के लिए उचित ओवरहेड भी जोड़ देगा। मैं इसकी अनुशंसा नहीं करता।

उपयोग करने के लिए थोड़ा कम भयानक विकल्प है LISTENऔर NOTIFY। PostgreSQL और LISTENघटनाओं के लिए एक बाहरी डेमॉन प्रक्रिया कनेक्ट करें । जब कोई तालिका बदलता है, तो तालिका को अधिसूचित पेलोड के रूप में तालिका में ON INSERT OR UPDATE OR DELETEभेजने के लिए ट्रिगर्स का उपयोग करें NOTIFY। लेन-देन शुरू होने पर ये भेजे जाते हैं। आपका डेमन परिवर्तन सूचनाओं को जमा कर सकता है और आलसी उन्हें डेटाबेस में एक मेज पर वापस लिख सकता है। यदि सिस्टम क्रैश हो जाता है, तो आप सबसे हाल के संशोधनों के अपने रिकॉर्ड को खो देते हैं, लेकिन यह ठीक है, यदि आप क्रैश के बाद शुरू कर रहे हैं, तो आप सभी तालिकाओं को बस संशोधित मानते हैं।

समवर्ती मुद्दों की सबसे खराब स्थिति से बचने के लिए आप बदले में एक टाइमस्टैम्प को before insert or update or delete or truncate on tablename for each statement executeट्रिगर का उपयोग करके लॉग कर सकते हैं , जो कि एक पैरामीटर के रूप में संबंध ओआईडी लेने के लिए सामान्यीकृत है। यह एक (relation_oid, timestamp)जोड़ी को एक परिवर्तन-लॉगिंग तालिका में सम्मिलित करेगा । फिर आपके पास एक अलग कनेक्शन पर एक सहायक प्रक्रिया होती है, या समय-समय पर आपके ऐप द्वारा कॉल की जाती है, नवीनतम जानकारी के लिए उस तालिका को एकत्रित करें, इसे हाल के परिवर्तनों के सारांश तालिका में मर्ज करें, और लॉग तालिका को काट दें। सुनो / अधिसूचित दृष्टिकोण पर इसका एकमात्र लाभ यह है कि यह दुर्घटना की जानकारी नहीं खोता है - लेकिन यह बहुत कम कुशल भी है।

एक और दृष्टिकोण एक सी विस्तार समारोह लिखने के लिए हो सकता है कि का उपयोग करता है (उदाहरण के लिए) ProcessUtility_hook, ExecutorRun_hook, आदि जाल तालिका परिवर्तन और lazily अद्यतन आँकड़े करने के लिए। मैंने यह देखने के लिए नहीं देखा कि यह कितना व्यावहारिक होगा; स्रोतों में विभिन्न _hook विकल्पों पर एक नज़र डालें।

सबसे अच्छा तरीका यह होगा कि इस जानकारी को रिकॉर्ड करने के लिए सांख्यिकी कोड को पैच किया जाए और कोर में शामिल करने के लिए PostgreSQL को एक पैच सबमिट किया जाए। सिर्फ कोड लिखकर शुरू न करें; एक बार अपने विचार को बढ़ाएं-एक बार जब आप इसके बारे में सोच लें कि इसे करने के लिए एक अच्छी तरह से परिभाषित तरीका है (यानी कोड को पढ़कर शुरू करें, तो "मैं कैसे करूं ..." पूछकर पोस्ट न करें)। अंतिम-अपडेट किए गए समय को जोड़ना अच्छा हो सकता है pg_stat_..., लेकिन आपको उस समुदाय को समझाना होगा, जो ओवरहेड के लायक था या इसे वैकल्पिक रूप से ट्रैक करने का एक तरीका प्रदान करता है - और आपको आँकड़े रखने के लिए कोड लिखना होगा और एक पैच सबमिट करें , क्योंकि केवल वही व्यक्ति जो यह सुविधा चाहता है, वह इससे परेशान होने वाला है।

मैं यह कैसे करूँगा

अगर मुझे ऐसा करना था, और इसे ठीक से करने के लिए एक पैच लिखने का समय नहीं था, तो मैं शायद ऊपर बताए गए सुनो / सूचित दृष्टिकोण का उपयोग करूंगा।

PostgreSQL 9.5 प्रतिबद्ध टाइमस्टैम्प के लिए अद्यतन

अपडेट : PostgreSQL 9.5 ने टाइमस्टैम्प बनाया है । यदि आपने उन्हें postgresql.conf(और अतीत में भी ऐसा किया है) सक्षम किया है, तो आप अंतिम संशोधित समय xminको अनुमानित करने के लिए पंक्ति के लिए प्रतिबद्ध टाइमस्टैम्प की जांच कर सकते हैं । यह केवल एक सन्निकटन है क्योंकि यदि सबसे हालिया पंक्तियों को हटा दिया गया है तो उन्हें गिना नहीं जाएगा।

इसके अलावा, प्रतिबद्ध टाइमस्टैम्प रिकॉर्ड केवल एक सीमित समय के लिए रखे जाते हैं। इसलिए यदि आप यह बताना चाहते हैं कि जब एक तालिका जो संशोधित नहीं है, तो संशोधित की गई है, तो उत्तर प्रभावी रूप से "डननो, थोड़ी देर पहले" होगा।


17

PostgreSQL 9.5 हमें पिछली संशोधित प्रतिबद्धताओं को ट्रैक करने दें।

  1. निम्न क्वेरी का उपयोग करके ट्रैक कमिट चालू या बंद है

    show track_commit_timestamp;
  2. यदि यह "ON" पर वापस जाता है तो चरण 3 पर जाएं postgresql.conf को संशोधित करें

    cd /etc/postgresql/9.5/main/
    vi postgresql.conf

    परिवर्तन

    track_commit_timestamp = off

    सेवा मेरे

    track_commit_timestamp = on

    सिस्टम को रिबूट करें

    दोहराएँ चरण 1।

  3. अंतिम कमिट को ट्रैक करने के लिए निम्नलिखित क्वेरी का उपयोग करें

    SELECT pg_xact_commit_timestamp(xmin), * FROM  YOUR_TABLE_NAME;
    
    SELECT pg_xact_commit_timestamp(xmin), * FROM YOUR_TABLE_NAME where COLUMN_NAME=VALUE;

1
आपको चरण 2 पर सिस्टम को रिबूट करने की आवश्यकता नहीं है। बस प्रक्रिया को पुनरारंभ करें। उदा sudo service postgresql restart
जोजफ

3

हां, इससे अपेक्षित व्यवहार किया जा सकता है - परिवर्तन के बारे में डेटा तुरंत लेनदेन लॉग में संग्रहीत किया जाता है। डेटा फ़ाइलों को चेकपॉइंट_ टाइमआउट देरी से अपडेट किया जा सकता है (डिफ़ॉल्ट 5 मिनट है)। Postgres स्थायी रूप से किसी भी समय अनुरोध नहीं करता है।


मुझे यकीन नहीं है कि मैं समझता हूं कि यह सवाल का जवाब कैसे देता है। हां, डेटा को लेन-देन लॉग में संग्रहीत किया जाता है, लेकिन इसका मतलब यह नहीं है कि किसी को एक विशिष्ट तालिका के लिए आसानी से संशोधन का समय मिल सकता है ( यदि वह सामग्री अभी भी लॉग में है तो लॉग लॉग कर सकता है, लेकिन चीजें फिर से नहीं मिल सकती हैं सर्र से)।
चार्ल्स डफी

यकीन है, आप लॉग से सभी आवश्यक जानकारी प्राप्त कर सकते हैं, लेकिन डेटा-माइल्स के माइम को निर्देशित किया गया था - डेटा फ़ाइलों का वास्तविककरण बहुत यादृच्छिक हो सकता है - कुछ सेकंड - कुछ मिनट (अधिकतम 1 घंटे) के बाद।
पावेल स्टीहुल

ओपी का खुद का प्रयास फाइलों को देखने के माध्यम से था, लेकिन उनका असली इरादा स्पष्ट रूप से एक टेबल माइम प्राप्त करना है। लेकिन हाँ, मैं समझता हूँ कि आप यहाँ कहाँ से आ रहे हैं (यह समझाते हुए कि वे काम क्यों नहीं कर रहे थे)।
चार्ल्स डफी

2

क्लाइंट एप्लिकेशन पर कुछ तालिकाओं के कैश को बनाए रखने के लिए मेरे पास लगभग समान आवश्यकता है। मैं लगभग कहता हूं , क्योंकि मुझे वास्तव में अंतिम संशोधन के समय को जानने की आवश्यकता नहीं है, लेकिन केवल यह पता लगाने के लिए कि पिछली बार कैश के सिंक्रनाइज़ होने के बाद कुछ बदल गया है या नहीं।

यहाँ मेरा दृष्टिकोण है:

बशर्ते आपके पास हर मेज पर एक idPK (PK), created_on(प्रविष्टि टाइमस्टैम्प) और updated_on(टाइमस्टैम्प अपडेट हो, NULL हो सकता है) कॉलम है, आप कर सकते हैं

SELECT id,greatest(created_on,updated_on) FROM %s ORDER BY greatest(created_on,updated_on) DESC LIMIT 1;

यदि आप इसे संक्षिप्त करते हैं और पंक्तियों की संख्या को पूर्व निर्धारित करते हैं, तो आप एक संस्करण टैग बना सकते हैं जो दिखता है count:id#timestamp, और यह तालिका में डेटा के हर संस्करण के लिए अद्वितीय होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.