2009-05-22 3 views
17

Я работаю с базой данных postgreSQL, которая обновляется партиями. Мне нужно знать, когда в последний раз, когда база данных (или таблица в базе данных) была обновлена ​​или изменена, либо будет делать.Как я могу найти последний раз, когда была обновлена ​​база данных PostgreSQL?

Я видел, что кто-то на форуме postgeSQL предложил использовать logging и запрашивать ваши журналы на время. Это не сработает для меня, так как у меня нет контроля над кодовой базой клиентов.

ответ

22

Вы можете написать trigger запускать каждый раз, когда вставка/обновление производится на определенную таблицу. Общее использование заключается в том, чтобы установить столбец «created» или «last_updated» строки в текущее время, но вы также можете обновить время в центральном местоположении, если вы не хотите изменять существующие таблицы.

Так, например, типичный способ заключается в следующем:

CREATE FUNCTION stamp_updated() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$ 
BEGIN 
    NEW.last_updated := now(); 
    RETURN NEW; 
END 
$$; 
-- repeat for each table you need to track: 
ALTER TABLE sometable ADD COLUMN last_updated TIMESTAMP; 
CREATE TRIGGER sometable_stamp_updated 
    BEFORE INSERT OR UPDATE ON sometable 
    FOR EACH ROW EXECUTE PROCEDURE stamp_updated(); 

Тогда, чтобы найти последнее обновление, вам необходимо выбрать «MAX (last_updated)» из каждой таблицы вы отслеживаете и взять наибольшую из них, например:

SELECT MAX(max_last_updated) FROM (
    SELECT MAX(last_updated) AS max_last_updated FROM sometable 
    UNION ALL 
    SELECT MAX(last_updated) FROM someothertable 
) updates 

для таблиц с последовательным (или аналогично сгенерированным) первичным ключом, вы можете попытаться избежать последовательного сканирования, чтобы найти последнее время обновления с помощью индекса первичного ключа, или создать индексы на last_updated.

-- get timestamp of row with highest id 
SELECT last_updated FROM sometable ORDER BY sometable_id DESC LIMIT 1 

Обратите внимание, что это может дать несколько неправильные результаты в случае идентификаторы не является вполне последовательным, но сколько точности нужно? (Имейте в виду, что транзакции означают, что строки могут стать видимыми для вас в другом порядке для их создания.)

Альтернативный подход, чтобы избежать добавления «обновленных» столбцов в каждую таблицу, состоит в том, чтобы иметь центральную таблицу для хранения обновлений проставлены в. Например:

CREATE TABLE update_log(table_name text PRIMARY KEY, updated timestamp NOT NULL DEFAULT now()); 
CREATE FUNCTION stamp_update_log() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$ 
BEGIN 
    INSERT INTO update_log(table_name) VALUES(TG_TABLE_NAME); 
    RETURN NEW; 
END 
$$; 
-- Repeat for each table you need to track: 
CREATE TRIGGER sometable_stamp_update_log 
AFTER INSERT OR UPDATE ON sometable 
FOR EACH STATEMENT EXECUTE stamp_update_log(); 

Это даст вам таблицу со строкой для каждого обновления таблицы: вы можете просто сделать:

SELECT MAX(updated) FROM update_log 

Чтобы получить время последнего обновления. (Вы могли бы разделить это по таблице, если хотите). Разумеется, эта таблица будет постоянно расти: либо создайте индекс на «обновленный» (который должен сделать последнее очень быстрым), либо обрезайте его периодически, если это соответствует вашему используемому случаю (например, возьмите исключительную блокировку на столе, получить последнее время обновления, а затем усечь его, если вам нужно периодически проверять, были ли внесены изменения).

Альтернативный подход, который может быть тем, о чем говорят люди на форуме, - это установить «log_statement = mod» в конфигурации базы данных (глобально для кластера, или в базе данных или для пользователя, которого необходимо отслеживать) и то все заявления, которые изменяют базу данных, будут записаны в журнал сервера. Затем вам нужно будет написать что-то за пределами базы данных, чтобы отсканировать журнал сервера, отфильтровать таблицы, которые вам не интересны, и т. Д.

4

Похоже, что вы можете использовать pg_stat_database, чтобы получить количество транзакций и проверить, если это изменяется от одного резервного пробега к следующему - см this dba.se answer и комментарии для получения более подробной информации

0

Вы можете написать хранимую процедуру в состоянии «ненадежный language "(например, plpythonu): Это позволяет получить доступ к файлам в папке postgres« base ». Верните большое количество файлов этих файлов в хранимую процедуру.

Но это только расплывчато, так как вакуум изменит эти файлы и mtime.

3

Мне нравится подход Джека. Вы можете запросить статистику таблицы и знать количество вставок, обновлений, удаления и так:

select n_tup_upd from pg_stat_user_tables where relname = 'YOUR_TABLE'; 

каждое обновление увеличит счет на 1.

голых в виде этот метод является жизнеспособным, если у вас есть одиночная БД. для нескольких экземпляров, вероятно, потребуется другой подход.