Tidak ada catatan yang dapat diandalkan dan otoritatif dari waktu tabel yang dimodifikasi terakhir. Menggunakan relfilenode salah karena banyak alasan:
Menulis awalnya dicatat ke log kepala-tulis (WAL), kemudian malas ke tumpukan (file tabel). Setelah catatan di WAL, Pg tidak terburu-buru untuk menulisnya ke heap, dan bahkan mungkin tidak ditulis sampai pos pemeriksaan sistem berikutnya;
Tabel yang lebih besar memiliki beberapa garpu, Anda harus memeriksa semua garpu dan memilih cap waktu terbaru;
Sederhana SELECT
dapat menghasilkan aktivitas menulis ke tabel di bawahnya karena pengaturan hint-bit;
autovaccum dan pemeliharaan lain yang tidak mengubah data yang terlihat pengguna masih memodifikasi file relasi;
beberapa operasi, seperti vaccum full
, akan menggantikan relfilenode. Mungkin tidak di tempat yang Anda harapkan jika Anda mencoba melihatnya bersamaan tanpa mengambil kunci yang sesuai.
Beberapa pilihan
Jika Anda tidak memerlukan keandalan, Anda dapat berpotensi menggunakan informasi dalam pg_stat_database
dan pg_stat_all_tables
. Ini dapat memberi Anda waktu reset statistik terakhir, dan statistik aktivitas sejak statistik terakhir direset. Itu tidak memberi tahu Anda ketika aktivitas terbaru adalah, hanya itu sejak statistik terakhir di-reset, dan tidak ada informasi tentang apa yang terjadi sebelum statistik itu di-reset. Jadi itu terbatas, tetapi sudah ada di sana.
Salah satu opsi untuk melakukannya dengan andal adalah menggunakan pemicu untuk memperbarui tabel yang berisi waktu terakhir yang dimodifikasi untuk setiap tabel. Ketahuilah bahwa melakukan hal itu akan membuat serial semua tulisan ke meja , menghancurkan konkurensi. Itu juga akan menambahkan sedikit overhead yang adil untuk setiap transaksi. Saya tidak merekomendasikannya.
Alternatif yang sedikit kurang mengerikan adalah menggunakan LISTEN
dan NOTIFY
. Minta proses daemon eksternal terhubung ke PostgreSQL dan LISTEN
untuk acara. Gunakan ON INSERT OR UPDATE OR DELETE
pemicu untuk mengirim NOTIFY
ketika tabel berubah, dengan tabel yang ditampilkan sebagai pemberitahuan muatan. Ini dikirim ketika transaksi dilakukan. Daemon Anda dapat mengakumulasikan notifikasi perubahan dan dengan malas menulisnya kembali ke tabel di database. Jika sistem macet, Anda kehilangan catatan modifikasi terbaru, tapi tidak apa-apa, Anda hanya memperlakukan semua tabel sebagai hanya dimodifikasi jika Anda memulai setelah crash.
Untuk menghindari masalah konkurensi yang paling buruk, Anda bisa mencatat perubahan cap waktu menggunakan before insert or update or delete or truncate on tablename for each statement execute
pemicu, digeneralisasi untuk mengambil relasi oid sebagai parameter. Ini akan menyisipkan (relation_oid, timestamp)
pasangan ke dalam tabel logging perubahan. Anda kemudian memiliki proses bantuan pada koneksi terpisah, atau dipanggil secara berkala oleh aplikasi Anda, mengagregasi tabel itu untuk info terbaru, menggabungkannya ke dalam tabel ringkasan perubahan terbaru, dan memotong tabel log. Satu-satunya keuntungan dari ini daripada pendekatan mendengarkan / memberi tahu adalah tidak kehilangan informasi saat macet - tetapi itu juga kurang efisien.
Pendekatan lain mungkin untuk menulis fungsi C ekstensi yang menggunakan (misalnya) ProcessUtility_hook
, ExecutorRun_hook
, dll untuk perubahan meja menjebak dan malas memperbarui statistik. Saya belum melihat bagaimana praktisnya ini; lihat berbagai opsi _hook di sumber.
Cara terbaik adalah dengan menambal kode statistik untuk merekam informasi ini dan mengirimkan tambalan ke PostgreSQL untuk dimasukkan dalam inti. Jangan hanya mulai dengan menulis kode; tingkatkan ide Anda pada -hackers setelah Anda cukup memikirkannya untuk memiliki cara yang jelas untuk melakukannya (yaitu mulai dengan membaca kode, jangan hanya memposting bertanya "bagaimana saya ..."). Mungkin menyenangkan untuk menambahkan waktu yang terakhir diperbarui pg_stat_...
, tetapi Anda harus meyakinkan komunitas bahwa itu sepadan dengan biaya overhead atau menyediakan cara untuk membuatnya dilacak secara opsional - dan Anda harus menulis kode untuk menjaga statistik dan kirimkan tambalan , karena hanya seseorang yang menginginkan fitur ini yang akan repot dengan itu.
Bagaimana saya melakukannya
Jika saya harus melakukan ini, dan tidak punya waktu untuk menulis tambalan untuk melakukannya dengan benar, saya mungkin akan menggunakan pendekatan mendengarkan / memberitahukan yang diuraikan di atas.
Pembaruan untuk cap waktu komitmen PostgreSQL 9.5
Pembaruan : PostgreSQL 9.5 memiliki cap waktu komit . Jika Anda mengaktifkannya di postgresql.conf
(dan melakukannya di masa lalu juga), Anda dapat memeriksa stempel waktu komit untuk baris dengan yang terbesar xmin
untuk memperkirakan waktu modifikasi terakhir. Ini hanya perkiraan karena jika baris terbaru telah dihapus mereka tidak akan dihitung.
Juga, catatan catatan waktu komit hanya disimpan untuk waktu yang terbatas. Jadi jika Anda ingin mengetahui kapan sebuah tabel yang tidak dimodifikasi banyak dimodifikasi, jawabannya secara efektif akan "tak tahu, beberapa saat yang lalu".