Не существует надежной, авторской записи последнего измененного времени таблицы. Использование relfilenode неправильно по многим причинам:
Записи сначала записываются в журнал головки записи (WAL), затем лениво в кучу (файлы таблиц). Когда запись находится в WAL, Pg не спешит записывать ее в кучу, и она может даже не записаться до следующей системной контрольной точки;
Большие столы имеют несколько вилок, вам нужно будет проверить все вилки и выбрать новейшую временную метку;
Простой SELECT
может генерировать операции записи в базовую таблицу из-за установки подсказки;
autovaccum и другое обслуживание, которое не изменяет видимые пользователю данные, все еще изменяет файлы отношения;
некоторые операции, например vaccum full
, заменят relfilenode. Это может быть не там, где вы ожидаете, если вы пытаетесь смотреть на него одновременно, не взяв соответствующую блокировку.
Несколько вариантов
Если вам не нужна надежность, вы можете использовать информацию в pg_stat_database
и pg_stat_all_tables
. Они могут дать вам время последнего сброса статистики и статистику активности с момента последнего сброса статистики. Он не сообщает вам, когда было последнее действие, только то, что это было с момента последнего сброса статистики, и нет никакой информации о том, что произошло до сброса этой статистики. Так что это ограничено, но это уже там.
Один из способов сделать это надежно - использовать триггер для обновления таблицы, содержащей время последнего изменения для каждой таблицы. Имейте в виду , что при этом будут сериализованы все записи в таблицу , что разрушит параллелизм. Это также добавит немало накладных расходов к каждой транзакции. Я не рекомендую это.
Немного менее ужасной альтернативой является использование LISTEN
и NOTIFY
. Подключите внешний процесс-демон к PostgreSQL и LISTEN
для событий. Используйте ON INSERT OR UPDATE OR DELETE
триггеры для отправки NOTIFY
s при изменении таблицы с таблицей oid в качестве полезной нагрузки notify. Они отправляются при фиксации транзакции. Ваш демон может накапливать уведомления об изменениях и лениво записывать их обратно в таблицу в базе данных. Если происходит сбой системы, вы теряете записи о последних изменениях, но это нормально, вы просто рассматриваете все таблицы как только что измененные, если запускаете после сбоя.
Чтобы избежать худшего из проблем параллелизма, вы могли бы вместо этого регистрировать временные метки изменения, используя 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
чтобы приблизить время последнего изменения. Это только приблизительное значение, потому что, если самые последние строки были удалены, они не будут учитываться.
Кроме того, записи отметок времени фиксации хранятся только в течение ограниченного времени. Так что, если вы хотите сказать, когда таблица, которая не была сильно изменена, будет изменена, ответ будет «не знаю, давно».