PostgreSQL 데이터베이스 테이블의 마지막 수정 날짜 가져 오기


35

이 답변에 설명 된대로 파일 수정 날짜를 확인하여 테이블이 수정 된 시점을 얻으려고합니다 . 그러나 결과가 항상 올바른 것은 아닙니다. 파일 수정 날짜는 테이블을 업데이트 한 후 몇 분 후에 업데이트됩니다. 올바른 행동입니까? PostgreSQL은 테이블 수정 사항을 일부 캐시에 저장 한 다음 하드 드라이브로 플러시합니까?

그렇다면 테이블의 올바른 마지막 수정 날짜를 어떻게 얻습니까 (자동 진공 수정도 괜찮다고 가정 해 봅시다)?

Linux Centos 6.2 x64에서 PostgreSQL 9.2를 사용합니다.


4
파일 수정 시간이 신뢰할 수 있다고 생각하지 않습니다. autovacuum으로 인해 변경 될 수도 있습니다. 신뢰할 수있는 유일한 방법은 트리거에 의해 유지 관리되는 수정 타임 스탬프를 테이블에 저장하는 것입니다.
a_horse_with_no_name

한 가지 아이디어는 WAL 파일에 저장된 정보가 트랜잭션 커밋 후 어느 정도 (짧거나 더 긴) 시간에 데이터 파일에 기록된다는 것입니다. 원한다면 이것을 캐시라고 부를 수 있습니다 :) 그렇지 않으면 @a_horse_with_no_name이 말한 것을 두 번째입니다.
dezso

답변:


35

테이블의 마지막 수정 시간에 대한 신뢰할 수 있고 권위있는 레코드가 없습니다. 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. 트랜잭션이 커밋 될 때 전송됩니다. 데몬은 변경 알림을 누적하여 지연 시간을 데이터베이스의 테이블에 다시 쓸 수 있습니다. 시스템이 충돌하면 가장 최근의 수정 기록이 손실되지만 괜찮습니다. 충돌 후 시작하면 모든 테이블을 방금 수정 된 것으로 간주합니다.

동시성 문제의 최악을 피하기 위해 대신 before insert or update or delete or truncate on tablename for each statement execute관계식을 매개 변수로 사용하도록 일반화 된 트리거를 사용하여 변경 타임 스탬프를 기록 할 수 있습니다. 그러면 (relation_oid, timestamp)변경 로깅 테이블에 쌍이 삽입 됩니다. 그런 다음 별도의 연결에서 도우미 프로세스를 갖거나 앱에서 주기적으로 호출하고 최신 정보를 위해 해당 테이블을 집계하여 최신 변경 사항을 요약 테이블로 병합 한 다음 로그 테이블을 자릅니다. 수신 / 알림 접근 방식에 비해이 방법의 유일한 장점은 충돌시 정보를 잃지 않지만 효율성도 떨어진다는 것입니다.

또 다른 방법은 C 확장 기능을 쓸 수 있습니다 그 용도 (예를 들어) ProcessUtility_hook, ExecutorRun_hook트랩 테이블 변경 및 느리게 업데이트 통계에 등. 나는 이것이 얼마나 실용적인지 보지 않았다. 소스의 다양한 _hook 옵션을 살펴보십시오.

가장 좋은 방법은 통계 코드를 패치하여이 정보를 기록하고 핵심에 포함시키기 위해 PostgreSQL에 패치를 제출하는 것입니다. 코드 작성만으로 시작하지 마십시오. 잘 정의 된 방법으로 할 수있을 정도로 충분히 생각한 후에는 해커에 대한 아이디어를 높이십시오 (예 : 코드를 읽는 것으로 시작하고 "어떻게해야합니까 ..."라고 게시하지 마십시오). 에 마지막 업데이트 시간을 추가하는 것이 좋을 수도 pg_stat_...있지만 오버 헤드에 가치가있는 커뮤니티를 설득하거나 선택적으로 추적 할 수있는 방법을 제공 해야합니다. 통계를 유지하려면 코드를 작성해야합니다. 패치를 제출하십시오. 이 기능을 원하는 사람 만이 그 기능을 방해 할 것입니다.

내가 어떻게

이 작업을 수행해야하는데 제대로 패치를 작성할 시간이 없다면 위에서 설명한 청취 / 알림 방법을 사용했을 것입니다.

PostgreSQL 9.5 커밋 타임 스탬프 업데이트

업데이트 : PostgreSQL 9.5에는 커밋 타임 스탬프가 있습니다. 당신이있는 경우 그들에 사용할 수 postgresql.conf, 당신은 가장 큰있는 행에 대한 타임 스탬프를 커밋 확인할 수 있습니다 (너무 과거에 그렇게) xmin대략 마지막으로 수정 된 시간. 가장 최근의 행이 삭제 된 경우에는 계산되지 않으므로 근사값 일뿐입니다.

또한 커밋 타임 스탬프 레코드는 제한된 시간 동안 만 유지됩니다. 따라서 많이 수정되지 않은 테이블을 언제 수정해야하는지에 대한 답을 얻으려면 실제로 "잠깐만"이라고 대답하면됩니다.


17

PostgreSQL 9.5에서는 마지막으로 수정 된 커밋을 추적 할 수 있습니다.

  1. 다음 쿼리를 사용하여 트랙 커밋 확인 또는 해제

    show track_commit_timestamp;
  2. "ON"을 반환하면 3 단계로 이동하십시오. 그렇지 않으면 postgresql.conf를 수정하십시오.

    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.
ijoseph

3

예, 이것은 예상대로 작동합니다. 변경에 대한 데이터는 즉시 트랜잭션 로그에 저장됩니다. 데이터 파일은 checkpoint_timeout 지연으로 업데이트 할 수 있습니다 (기본값은 5 분). Postgres는 요청한 시간을 영구적으로 유지하지 않습니다.


이것이 어떻게 질문에 대답하는지 잘 모르겠습니다. 예, 데이터는 트랜잭션 로그에 저장되지만, 그 하나는 (쉽게 특정 테이블에 대한 수정 시간을 얻을 수 있다는 것을 의미하지 않는다 경우 그 내용이 로그를 분석 할 수있는 로그 하나 아직이지만, 상황이 오히려 밖으로 재생 얻을 빨리).
Charles Duffy

물론, 필요한 모든 정보를 로그에서 얻을 수 있지만 질문은 mtime의 데이터 파일에 관한 것입니다. 데이터 파일의 실제화는 커밋 후 몇 초-몇 분 (최대 1 시간)에 이르기까지 매우 임의적 일 수 있습니다.
Pavel Stehule

OP의 자체 시도는 파일을 살펴 보는 것이었지만 실제 의도 는 분명히 테이블 타임을 얻는 것입니다. 그러나 네, 나는 당신이 여기에서 어디로 왔는지 이해합니다 (왜 그들이하고 있었는지 설명하지 못했습니다).
Charles Duffy

2

나는이 거의 클라이언트 응용 프로그램에서 일부 테이블의 캐시를 유지하기 위해 같은 요구 사항을. 나는 거의 마지막 이라고 말합니다. 마지막으로 수정 한 시간을 알 필요는 없지만 캐시가 마지막으로 동기화 된 이후로 무언가가 변경되었는지 감지하기 위해서입니다.

내 접근 방식은 다음과 같습니다.

당신이 가지고 제공 id(PK), created_on(삽입 타임 스탬프) 및 updated_on모든 테이블에 열 (업데이트 타임 스탬프를, NULL이 될 수 있음)을 수행 할 수 있습니다

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.