Немає достовірних, авторських записів останнього зміненого часу таблиці. Використання релфіленода неправильно з багатьох причин:
Записи спочатку записуються в журнал запису голови (WAL), потім ліниво кучу (файли таблиці). Після того, як запис знаходиться в WAL, Pg не поспішає записувати його в купу, і він може навіть не записатись до наступної контрольної точки системи;
Більші таблиці мають декілька виделок, вам доведеться перевірити всі вилки та вибрати найновішу часову позначку;
Простий SELECT
може генерувати активність запису до базової таблиці завдяки налаштуванням бітових підказок;
autovaccum та інше обслуговування, яке не змінює видимі для користувача дані, все ще змінює файли відношень;
деякі операції, як-от vaccum full
, замінять релфіленод. Можливо, ви не будете там, де ви очікуєте, якщо ви намагаєтесь поглянути на це одночасно, не взявши відповідний замок.
Кілька варіантів
Якщо вам не потрібна надійність, ви потенційно можете використовувати інформацію в pg_stat_database
і pg_stat_all_tables
. Вони можуть дати тобі час останнього скидання статистики та статистику активності після останнього скидання статистики. Це не говорить вам про те, коли була остання активність, лише про те, що це було з моменту останнього скидання статистики, і немає інформації про те, що сталося до цього скидання. Так що це обмежено, але воно вже є.
Одним із варіантів надійної роботи є використання тригера для оновлення таблиці, що містить останні змінені часи для кожної таблиці. Будьте в курсі, що це буде серіалізувати всі записи в стіл , знищуючи одночасність. Це також додасть неабиякі накладні витрати до кожної транзакції. Я не рекомендую.
Трохи менш жахливою альтернативою є використання LISTEN
та NOTIFY
. Запропонуйте зовнішній процес демон підключитися до PostgreSQL та LISTEN
для подій. Використовуйте ON INSERT OR UPDATE OR DELETE
тригери для надсилання NOTIFY
s, коли таблиця змінюється, при цьому таблиця є oid як корисне навантаження сповіщення. Вони надсилаються, коли транзакція вчиняється. Ваш демон може накопичувати сповіщення про зміни і ліниво записувати їх назад до таблиці в базі даних. Якщо система виходить з ладу, ви втрачаєте запис останніх модифікацій, але це нормально, ви просто ставитесь до всіх таблиць як щойно змінених, якщо ви запускаєтесь після аварії.
Щоб уникнути найгірших проблем з паралельністю, ви можете замість цього записувати часові позначки змін за допомогою before insert or update or delete or truncate on tablename for each statement execute
тригера, узагальненого, щоб прийняти відношення oid як параметр. Це дозволить вставити (relation_oid, timestamp)
пару в таблицю реєстрації змін. Потім у вас є допоміжний процес на окремому з’єднанні або періодично викликається вашим додатком, агрегуйте цю таблицю для останньої інформації, об'єднайте її в підсумкову таблицю останніх змін та врізайте таблицю журналів. Єдиною перевагою цього перед підходом до прослуховування / оповіщення є те, що він не втрачає інформацію про аварійне завершення, але це ще менш ефективно.
Іншим підходом може бути написання функції розширення C, яка використовує (наприклад) ProcessUtility_hook
, ExecutorRun_hook
і т.д., щоб відслідковувати зміни таблиці та ліниво оновлювати статистику. Я не дивився, щоб це було практично; погляньте на різні параметри _hook у джерелах.
Найкращим способом було б виправити код статистики для запису цієї інформації та подати патч до PostgreSQL для включення в ядро. Не починайте просто з написання коду; підніміть свою ідею на -хакерів, як тільки ви подумаєте над цим достатньо, щоб мати чітко визначений спосіб це зробити (тобто почніть з читання коду, не просто публікуйте запитання "як мені ..."). Можливо, приємно додати останні оновлені часи pg_stat_...
, але вам доведеться переконати громаду, що вона стоїть накладні витрати або запропонувати спосіб зробити її необов'язково відстежувати - і вам доведеться написати код, щоб зберегти статистику та Надішліть виправлення , тому що лише хтось, хто хоче цю функцію, збирається потурбуватися цим.
Як я це зробив
Якби я мав це зробити, і не мав часу написати патч, щоб зробити це належним чином, я, мабуть, скористався підходом прослуховування / сповіщення, описаним вище.
Оновлення для часових міток PostgreSQL 9.5
Оновлення : PostgreSQL 9.5 має часові позначки . Якщо їх увімкнено postgresql.conf
(і це робилося і в минулому), ви можете перевірити часову позначку для рядка з найвищим значенням xmin
для приблизного останнього зміненого часу. Це лише наближення, тому що якщо видалено останні останні рядки, вони не будуть зараховані.
Крім того, записи часових міток фіксації зберігаються лише обмежений час. Отже, якщо ви хочете сказати, коли таблиця, яка не дуже модифікована, модифікована, відповідь фактично буде "давно, час тому".