পোস্টগ্রিএসকিউএল ডাটাবেস সারণির সর্বশেষ পরিবর্তনের তারিখ পাওয়া


35

আমার টেবিলটি যখন বর্ণিত হয়েছে তেমন ফাইলের পরিবর্তনের তারিখটি পরীক্ষা করে এটি সংশোধন করার চেষ্টা করছে এই উত্তরে । তবে ফলাফল সর্বদা সঠিক হয় না। আমি আমার টেবিলটি আপডেট করার পরে কয়েক মিনিটের মধ্যে ফাইল পরিবর্তনের তারিখ আপডেট হয়। এটা কি সঠিক আচরণ? পোস্টগ্রিএসকিউএল কিছু ক্যাশে টেবিল পরিবর্তনগুলি সঞ্চয় করে এবং তারপরে এটি হার্ড ড্রাইভে ফ্লাশ করে?

সুতরাং, আমি কীভাবে কোনও টেবিলের সঠিক শেষ সংশোধন তারিখ পাব (আসুন ধরে নেওয়া যাক যে স্বয়ংক্রিয় ভ্যাকুয়াম পরিবর্তনগুলিও ঠিক আছে)?

আমি লিনাক্স সেন্টোস 6.2 এক্স 64 এর অধীনে পোস্টগ্রিজ এসকিউএল 9.2 ব্যবহার করি।


4
আমি মনে করি না ফাইল পরিবর্তনের সময়টি নির্ভরযোগ্য। এটি অটোভ্যাকুমের কারণেও পরিবর্তন হতে পারে। একমাত্র নির্ভরযোগ্য উপায় হ'ল আপনার টেবিলে একটি সংশোধন টাইমস্ট্যাম্প সংরক্ষণ করা, একটি ট্রিগার দ্বারা রক্ষণাবেক্ষণ করা।
a_horse_with_no_name

একটি ধারণা হ'ল ডাব্লুএল ফাইলগুলিতে সঞ্চিত তথ্য লেনদেন করার পরে কিছু (সংক্ষিপ্ত বা দীর্ঘ) সময় তথ্য ফাইলগুলিতে লেখা হয়। আপনি যদি চান, আপনি এটিকে ক্যাশে বলতে পারেন :) অন্যথায়, @ এ_হর্স_বিহীন_নাম_নাম কী বলেছিল তা আমি দ্বিতীয় স্থানে রেখেছি।
dezso

উত্তর:


35

কোনও সারণির শেষ পরিবর্তিত সময়ের কোনও নির্ভরযোগ্য, রচয়িতা রেকর্ড নেই। বিভিন্ন কারণে রিফ্লাইনেড ব্যবহার করা ভুল:

  • লেখাগুলি প্রথমে রাইটিং-হেড লগ (ওয়াল) এ রেকর্ড করা হয়, তারপরে অলসভাবে গাদা (টেবিল ফাইল) এ রেকর্ড করা হয় । রেকর্ডটি একবার ওএল-তে থাকলে, পিজি এটি গাদা লিখতে ছুটে যায় না এবং পরবর্তী সিস্টেমের চেকপয়েন্ট পর্যন্ত এটি লেখাও হতে পারে না;

  • বড় টেবিলগুলিতে একাধিক কাঁটাচামচ রয়েছে, আপনাকে সমস্ত কাঁটাচামচ পরীক্ষা করতে হবে এবং নতুন টাইমস্ট্যাম্প বাছাই করতে হবে;

  • কোনও সাধারণ SELECTইঙ্গিত-বিট সেটিংয়ের কারণে অন্তর্নিহিত টেবিলটিতে লেখার ক্রিয়াকলাপ উত্পন্ন করতে পারে;

  • অটোভ্যাকম এবং অন্যান্য রক্ষণাবেক্ষণ যা ব্যবহারকারীর দৃশ্যমান ডেটা পরিবর্তন করে না এখনও সম্পর্ক ফাইলগুলিকে সংশোধন করে;

  • কিছু ক্রিয়াকলাপ, যেমন vaccum full, রিফ্লেইনডকে প্রতিস্থাপন করবে। আপনি যদি উপযুক্ত লক না নিয়ে একযোগে এটি দেখার চেষ্টা করছেন তবে আপনি যেখানে আশা করছেন তা তা নাও হতে পারে।

কয়েকটি বিকল্প

আপনার যদি নির্ভরযোগ্যতার প্রয়োজন না হয় তবে আপনি সম্ভাব্যভাবে তথ্যটি ইন pg_stat_databaseএবং ব্যবহার করতে পারেন pg_stat_all_tables। এগুলি আপনাকে সর্বশেষ পরিসংখ্যান পুনরায় সেট করার সময় দিতে পারে এবং শেষ পরিসংখ্যান পুনরায় সেট করার পরে ক্রিয়াকলাপের পরিসংখ্যান । এটি আপনাকে জানায় না যে সর্বাধিক সাম্প্রতিক ক্রিয়াকলাপটি কখন হয়েছিল, কেবলমাত্র এটি ছিল শেষ পরিসংখ্যানগুলি পুনরায় সেট করার পরে, এবং সেই পরিসংখ্যান পুনরায় সেট হওয়ার আগে কী হয়েছিল সে সম্পর্কে কোনও তথ্য নেই। সুতরাং এটি সীমাবদ্ধ তবে এটি ইতিমধ্যে রয়েছে।

এটি নির্ভরযোগ্যভাবে করার জন্য একটি বিকল্প হ'ল প্রতিটি টেবিলের জন্য শেষ-সংশোধিত সময় সমেত একটি টেবিল আপডেট করতে একটি ট্রিগার ব্যবহার করা। সচেতন থাকুন যে এটি করার ফলে টেবিলে সমস্ত লেখাগুলিকে সিরিয়ালাইজ করা হবে , সম্মতিটি নষ্ট হবে। এটি প্রতিটি লেনদেনে মোটামুটি ওভারহেড যুক্ত করবে। আমি এটি সুপারিশ না।

কিছুটা কম ভয়ঙ্কর বিকল্প হ'ল ব্যবহার করা LISTENএবং NOTIFY। একটি বহিরাগত ডেমন প্রক্রিয়া পোস্টগ্রেএসকিউএল এবং 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ইত্যাদি ফাঁদ টেবিল পরিবর্তন এবং প্রখর রৌদ্রে আপডেট পরিসংখ্যান করতে। এটি কতটা বাস্তব হবে তা দেখার জন্য আমি তাকাতে পারি নি; উত্সে বিভিন্ন _ হুক বিকল্পগুলি একবার দেখুন।

সর্বোত্তম উপায় হ'ল এই তথ্য রেকর্ড করার জন্য পরিসংখ্যান কোডটি প্যাচ করা এবং মূল অন্তর্ভুক্তির জন্য পোস্টগ্র্রেএসকিউএলে একটি প্যাচ জমা দেওয়া। শুধু কোড লিখে শুরু করবেন না; হ্যাকারদের উপর আপনার ধারণাটি উত্থাপন করুন একবার আপনি এটির জন্য একটি ভাল সংজ্ঞায়িত উপায় থাকার জন্য যথেষ্ট ভেবে দেখেছেন (উদাহরণস্বরূপ কোডটি পড়া শুরু করুন, "আমি কীভাবে করব ..." জিজ্ঞাসা করে পোস্ট করবেন না)। pg_stat_...এটিতে সর্বশেষ আপডেট হওয়া সময়গুলি যোগ করা ভাল হতে পারে , তবে আপনাকে সম্প্রদায়টি বোঝাতে হবে যে এটি ওভারহেডের পক্ষে মূল্যবান ছিল বা এটি বিকল্পভাবে ট্র্যাক করার একটি উপায় সরবরাহ করতে পারে - এবং আপনাকে পরিসংখ্যানগুলি রাখতে কোড লিখতে হবে এবং একটি প্যাচ জমা দিন , কারণ এই বৈশিষ্ট্যটি কেবল যারাই চায় এটি নিয়ে বিরক্ত হয়।

আমি এটা কিভাবে করব

যদি আমার এটি করতে হয়, এবং এটি সঠিকভাবে করার জন্য কোনও প্যাচ লেখার সময় না পেয়ে আমি সম্ভবত উপরে বর্ণিত শ্রবণ / বিজ্ঞপ্তিটি ব্যবহার করব।

PostgreSQL 9.5 কমিট টাইমস্ট্যাম্পগুলির জন্য আপডেট

আপডেট : পোস্টগ্রিসকিউএল 9.5 এর টাইমস্ট্যাম্প রয়েছে । আপনি যদি তাদের মধ্যে সক্রিয় postgresql.conf(এবং অতীতে খুবই করেছিলেন), আপনি পরীক্ষা করতে পারবেন সর্বশ্রেষ্ঠ সঙ্গে সারিতে টাইমস্ট্যাম্প কমিট xminকরতে আনুমানিক সর্বশেষ সংশোধিত সময়। এটি কেবলমাত্র একটি আনুমানিক কারণ কারণ সর্বাধিক সাম্প্রতিক সারিগুলি মুছে ফেলা হলে সেগুলি গণনা করা হবে না।

এছাড়াও, প্রতিশ্রুতিবদ্ধ টাইমস্ট্যাম্প রেকর্ডগুলি কেবলমাত্র একটি সীমিত সময়ের জন্য রাখা হয়। সুতরাং যদি আপনি যদি বলতে চান যে কোনও টেবিল যা খুব বেশি সংশোধিত হয় না তখন উত্তরটি কার্যকরভাবে "ডুনো, কিছুক্ষণ আগে" হয়ে যাবে।


17

PostgreSQL 9.5 আমাদের সর্বশেষ পরিবর্তিত প্রতিশ্রুতি ট্র্যাক করতে দিন।

  1. নিম্নলিখিত কোয়েরিটি ব্যবহার করে চেক ট্র্যাক কমিট চালু বা বন্ধ রয়েছে

    show track_commit_timestamp;
  2. যদি এটি "চালু" ফিরে আসে তবে পদক্ষেপ 3 এ যান অন্য পোস্টগ্রেএসএলএলসিএফ পরিবর্তন করুন

    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 মিনিট হয়)। আপনার অনুরোধের সময় পোস্টগ্রিজ স্থায়ীভাবে ধরে রাখে না।


আমি নিশ্চিত না যে আমি কীভাবে এই প্রশ্নের উত্তর দিয়েছি তা বুঝতে পেরেছি। হ্যাঁ, ডেটা লেনদেনের লগে সংরক্ষিত থাকে তবে এর অর্থ এই নয় যে সহজেই একটি নির্দিষ্ট টেবিলের জন্য কোনও পরিবর্তনের সময় পাওয়া যায় ( যদি সেই সামগ্রীটি লগতে থাকে তবে লগটি পার্স করতে পারে তবে জিনিসগুলি বরং পুনরায় খেলানো হবে) দ্রুত)।
চার্লস ডাফি

অবশ্যই, আপনি লগ থেকে সমস্ত প্রয়োজনীয় তথ্য পেতে পারেন, তবে প্রশ্নগুলি ডেটাফাইলে এমটাইম-এর দিকে পরিচালিত হয়েছিল - ডেটা ফাইলের বাস্তবায়ন হতে পারে বেশ এলোমেলো - কয়েক সেকেন্ড - কয়েক মিনিট (সর্বাধিক 1 ঘন্টা) কমিট করার পরে।
পাভেল স্টেহুল

ওপি-র নিজস্ব প্রচেষ্টা ফাইলগুলি দেখার মাধ্যমে ছিল, তবে তাদের আসল উদ্দেশ্যটি একটি টেবিল এমটাইম পাওয়ার পক্ষে স্পষ্ট। তবে হ্যাঁ, আমি বুঝতে পেরেছি আপনি এখান থেকে আসছেন (তারা কী করছিল তা কেন কাজ করছে তা ব্যাখ্যা করে)।
চার্লস ডাফি

2

ক্লায়েন্ট অ্যাপ্লিকেশনটিতে কিছু টেবিলের ক্যাশে বজায় রাখার জন্য আমার প্রায় একই প্রয়োজনীয়তা রয়েছে। আমি বলি প্রায় , কারণ শেষ পরিবর্তনের সময়টি আমার সত্যিকারের জানা দরকার ছিল না, তবে কেবল ক্যাশে সিঙ্ক্রোনাইজ হওয়ার সময় থেকে কিছু পরিবর্তন হয়েছে কিনা তা সনাক্ত করতে হবে।

এখানে আমার পদ্ধতির:

আপনি যদি প্রতিটি টেবিলে একটি id(পিকে), created_on(সন্নিবেশ টাইমস্ট্যাম্প) এবং updated_on(আপডেট টাইমস্ট্যাম্প, ন্যূনুয়াল হতে পারে) কলামটি সরবরাহ করেন তবে আপনি তা করতে পারেন

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

আপনি যদি এটিকে একত্রী করে রাখেন এবং সারিগুলির সংখ্যাটি আগে থেকে চালিয়ে যান তবে আপনি দেখতে একটি সংস্করণ ট্যাগ তৈরি করতে পারেন count:id#timestampএবং এটি টেবিলের ডেটার প্রতিটি সংস্করণের জন্য স্বতন্ত্র হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.