Nie ma wiarygodnego, autorytatywnego zapisu czasu ostatniej modyfikacji tabeli. Korzystanie z relfilenode jest nieprawidłowe z wielu powodów:
Zapisy są początkowo zapisywane w dzienniku głowicy zapisu (WAL), a następnie leniwie na stosie (pliki tabel). Gdy rekord znajduje się w WAL, Pg nie spieszy się z zapisaniem go na stercie i może nawet nie zostać zapisany do następnego punktu kontrolnego systemu;
Większe tabele mają wiele widelców, należy sprawdzić wszystkie widelce i wybrać najnowszy znacznik czasu;
Prosty SELECT
może generować działanie zapisu do podstawowej tabeli ze względu na ustawienie bitu podpowiedzi;
autovaccum i inna konserwacja, która nie zmienia widocznych danych użytkownika, nadal modyfikuje pliki relacji;
niektóre operacje, na przykład vaccum full
, zastąpią relfilenode. To może nie być to, czego oczekujesz, jeśli próbujesz spojrzeć na to jednocześnie bez odpowiedniej blokady.
Kilka opcji
Jeśli nie potrzebujesz niezawodności, możesz potencjalnie wykorzystać informacje w pg_stat_database
i pg_stat_all_tables
. Mogą dać ci czas ostatniego resetu statystyk oraz statystyki aktywności od czasu ostatniego resetowania statystyk. Nie mówi ci, kiedy była ostatnia aktywność, tyle że od ostatniego resetu statystyk i nie ma informacji o tym, co się stało przed zresetowaniem statystyk. Więc jest ograniczony, ale już tam jest.
Jedną z opcji niezawodnego działania jest użycie wyzwalacza do aktualizacji tabeli zawierającej czasy ostatniej modyfikacji dla każdej tabeli. Pamiętaj, że spowoduje to szeregowanie wszystkich zapisów do tabeli , niszcząc współbieżność. Doda to również sporo kosztów ogólnych do każdej transakcji. Nie polecam tego
Nieco mniej okropną alternatywą jest użycie LISTEN
i NOTIFY
. Niech zewnętrzny proces demona połączy się z PostgreSQL i LISTEN
dla zdarzeń. Użyj ON INSERT OR UPDATE OR DELETE
wyzwalaczy, aby wysłać NOTIFY
s, gdy zmienia się tabela, z oid tabeli jako ładunkiem powiadomienia. Są one wysyłane po zatwierdzeniu transakcji. Twój demon może gromadzić powiadomienia o zmianach i leniwie zapisywać je z powrotem do tabeli w bazie danych. Jeśli system ulegnie awarii, stracisz rejestr ostatnich modyfikacji, ale to jest ok, traktujesz wszystkie tabele jako właśnie zmodyfikowane, jeśli zaczynasz po awarii.
Aby uniknąć najgorszych problemów z współbieżnością, zamiast tego można rejestrować znaczniki czasu zmiany za pomocą before insert or update or delete or truncate on tablename for each statement execute
wyzwalacza, uogólnionego w celu uwzględnienia oid relacji jako parametru. Spowodowałoby to wstawienie (relation_oid, timestamp)
pary do tabeli rejestrowania zmian. Następnie masz proces pomocniczy na oddzielnym połączeniu lub wywoływany okresowo przez aplikację, agregujesz tę tabelę, aby uzyskać najnowsze informacje, scalasz ją z tabelą podsumowań najnowszych zmian i obcinasz tabelę dziennika. Jedyną zaletą tego rozwiązania w porównaniu z metodą nasłuchiwania / powiadamiania jest to, że nie traci informacji w przypadku awarii - ale jest jeszcze mniej wydajny.
Innym rozwiązaniem może być napisać funkcję przedłużacza C, który używa (np) ProcessUtility_hook
, ExecutorRun_hook
itp do zmian stołowych pułapkę i leniwie statystykach aktualizacji. Nie zastanawiałem się, czy byłoby to praktyczne; spójrz na różne opcje _hook w źródłach.
Najlepszym sposobem byłoby załatanie kodu statystycznego, aby zapisać te informacje i przesłać łatkę do PostgreSQL w celu włączenia do rdzenia. Nie zaczynaj od pisania kodu; podnieś swój pomysł na -hakerów, gdy tylko pomyślisz o tym wystarczająco, aby mieć dobrze zdefiniowany sposób na zrobienie tego (tj. zacznij od przeczytania kodu, nie po prostu pytaj „jak mam ...”). Przydałoby się dodać czasy ostatniej aktualizacji pg_stat_...
, ale musiałbyś przekonać społeczność, że warto było to narzucić, lub podać sposób opcjonalnego śledzenia - i musiałbyś napisać kod, aby zachować statystyki i prześlij łatkę , ponieważ tylko ktoś, kto chce tej funkcji, będzie się tym przejmował.
Jak bym to zrobił
Gdybym musiał to zrobić i nie miałbym czasu, aby napisać łatkę, aby zrobić to poprawnie, prawdopodobnie skorzystałbym z metody słuchania / powiadamiania opisanej powyżej.
Aktualizacja znaczników czasu zatwierdzania PostgreSQL 9.5
Aktualizacja : PostgreSQL 9.5 ma znaczniki czasu zatwierdzenia . Jeśli masz je włączone w postgresql.conf
(i robiłeś to również w przeszłości), możesz sprawdzić znacznik czasu zatwierdzenia dla wiersza z największym, xmin
aby przybliżać czas ostatniej modyfikacji. Jest to tylko przybliżenie, ponieważ jeśli najnowsze wiersze zostaną usunięte, nie zostaną zliczone.
Ponadto zapisy datownika zatwierdzenia są przechowywane tylko przez ograniczony czas. Więc jeśli chcesz powiedzieć, kiedy tabela, która nie jest dużo zmodyfikowana, jest zmodyfikowana, odpowiedź będzie brzmiała „nie wiem, jakiś czas temu”.