Saya mencoba untuk mendapatkan ketika tabel saya dimodifikasi dengan memeriksa tanggal modifikasi file seperti yang dijelaskan dalam jawaban ini . Tetapi hasilnya tidak selalu benar. Tanggal modifikasi file diperbarui dalam beberapa menit setelah saya memperbarui tabel saya. Apakah itu perilaku yang benar? Apakah PostgreSQL menyimpan modifikasi tabel dalam beberapa cache dan kemudian memindahkannya ke hard drive?
Jadi, bagaimana saya mendapatkan tanggal modifikasi terakhir yang benar dari sebuah tabel (mari kita asumsikan bahwa modifikasi vakum otomatis juga ok)?
Saya menggunakan PostgreSQL 9.2 di Linux Centos 6.2 x64.
postgresql
gulungan
sumber
sumber
Jawaban:
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
danpg_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
danNOTIFY
. Minta proses daemon eksternal terhubung ke PostgreSQL danLISTEN
untuk acara. GunakanON INSERT OR UPDATE OR DELETE
pemicu untuk mengirimNOTIFY
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 terbesarxmin
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".
sumber
PostgreSQL 9.5 mari kita lacak komit terakhir yang dimodifikasi.
Periksa komit trek aktif atau nonaktif menggunakan kueri berikut
Jika kembali "ON" lanjutkan ke langkah 3 lain memodifikasi postgresql.conf
Perubahan
untuk
Mulai ulang sistem
Ulangi langkah 1.
Gunakan kueri berikut untuk melacak komit terakhir
sumber
sudo service postgresql restart
.Ya, ini bisa diharapkan berperilaku - data tentang perubahan disimpan ke log transaksi segera. File data dapat diperbarui dengan penundaan checkpoint_timeout (standarnya adalah 5 menit). Postgres tidak tahan secara permanen kapan pun Anda minta.
sumber
Saya memiliki persyaratan yang hampir sama untuk menjaga cache dari beberapa tabel pada aplikasi klien. Saya katakan hampir , karena saya tidak benar-benar perlu tahu waktu modifikasi terakhir, tetapi hanya untuk mendeteksi jika ada sesuatu yang berubah sejak terakhir kali cache disinkronkan.
Inilah pendekatan saya:
Asalkan Anda memiliki kolom
id
(PK),created_on
(timestamp penyisipan) danupdated_on
(memperbarui timestamp, mungkin NULL) pada setiap tabel, Anda dapatJika Anda menyatukan ini dan menambahkan jumlah baris, Anda bisa membuat tag versi yang terlihat
count:id#timestamp
, dan itu akan unik untuk setiap versi data dalam tabel.sumber