- Q1. Apakah PG memiliki kemampuan untuk menyimpan/menghangatkan relasi?
- Q2. Apakah mungkin untuk kembali ke keadaan cache sebelumnya di mana ia ditinggalkan sebelum mematikan server database karena pemeliharaan ?
Dalam rilis PostgreSQL sebelumnya, tidak ada kemungkinan untuk menghangatkan relasi atau menyimpan status cache, tetapi dari PostgreSQL 9.4 dan seterusnya setiap kueri di atas (Q1, Q2) ditangani dengan dua modul contrib pg_prewarm dan pg_hibernator . Terlepas dari kenyataan bahwa mereka berbeda dalam kepraktisan, namun kombinasi tampaknya sangat layak dan berguna di masa depan untuk DBA. Singkatnya tentang kontribusi:
pg_prewarm contrib (Penulis:Robert Haas), menyediakan kemampuan untuk memuat data relasi ke dalam cache buffer OS atau cache buffer PG. Ini memiliki fungsi nomor blok pertama atau terakhir untuk pemanasan. (Catatan:Ini tidak memiliki perlindungan khusus pada data pra-pemanasan dari penggusuran cache dan juga jika instance database dimulai ulang maka diperlukan penghangatan ulang pada relasi).
pg_hibernator contrib (Penulis:Gurjeet Singh), menyediakan kemampuan untuk secara otomatis menyimpan daftar isi buffer bersama ke disk pada shutdown database, dan secara otomatis mengembalikan buffer pada startup database, sama seperti menyimpan/mengembalikan snapshot shared_buffers. Itu menggunakan modul PG 9.3 untuk mendaftarkan "proses pekerja latar belakang" dan memunculkan dua proses "Buffer Saver", "Buffer Reader" untuk menyimpan/mengembalikan. Menariknya, dengan sedikit peretasan, pg_hibernator juga dapat mengizinkan budak siaga untuk mulai melayani kueri dengan kecepatan penuh dengan konten master yang sama, akan melihatnya dalam satu menit :).
Terakhir, kita perlu pg_buffercache modul untuk melihat ke dalam konten saat ini dari shared_buffers PostgreSQL. Modul ini membantu memahami persentase buffer yang ditempati oleh suatu relasi.
Mari kita mainkan semua kontribusi ini dan lihat bagaimana mereka memenuhi tujuan dari dua pertanyaan (Q1,Q2). Saya akan menggunakan tabel 'foo' berukuran 885MB di VM lokal saya, bersama dengan kueri pg_buffercache standar.
PILIH c.relname,
count(*) SEBAGAI buffer
DARI pg_class c
INNER JOIN pg_buffercache b PADA b.relfilenode=c.relfilenode DAN c.relname='foo'
INNER JOIN pg_database d ON (b.reldatabase=d.oid AND d.datname=current_database())
GROUP BY c.relname
ORDER BY 2 DESC LIMIT 10;
Penggunaan pg_prewarm contrib dan pemanasan tabel 'foo'.
postgres=# buat ekstensi pg_prewarm;
CREATE EXTENSION
postgres=# dt+
Daftar relasi
Skema | Nama | Ketik | Pemilik | Ukuran | Deskripsi
--------+------+-------+----------+--------+- ------------
publik | foo | meja | postgres | 885 MB |
(1 baris)
postgres=# pilih pg_prewarm('foo');
pg_prewarm
------------
113278
(1 baris)
--pg_buffercache keluaran kueri
relname | buffer
---------+---------
foo | 113278
(1 baris)Penggunaan pg_prewarm yang sangat sederhana dan langsung dengan output blok yang dihangatkan di shared_buffers untuk relasi 'foo'. Dari pg_buffercache output kueri kita dapat mengevaluasinya bahwa ada buffer 113278 (113278 * 8 / 1024 =884MB ) dengan ukuran blok 8KB dari relasi 'foo' yang cocok dengan output pg_prewarm. Di sini, jika server Postgres dimulai ulang karena suatu alasan, shared_buffers kosong dan DBA perlu melakukan penghangatan ulang untuk kembali ke tahap penghangatan sebelumnya. Untuk satu meja, penghangatan ulang selalu sederhana kecuali untuk sekelompok tabel yang menyakitkan.
Pada titik ini, kita dapat menggunakan pg_hibernator contrib, karena memiliki fleksibilitas untuk menyimpan konten shared_buffer dan mengembalikannya saat startup. Mari aktifkan pg_hibernator/pg_prewarm bersama-sama dan jalankan latihan serupa hanya dengan memasukkan satu langkah restart dan lihat apakah status cache kembali seperti semula atau tidak. Saya tidak akan membahas instalasi pg_hibernator, karena pada git dijelaskan dengan sangat baik, namun saya akan langsung melompat ke bagian implementasi dan memulai server dengan pg_hibernator.
postgres 24623 1 0 02:06 pts/4 00:00:00 /usr/local/pgpatch/pg/bin/postgres -D /usr/local/pgpatch/pg/data_10407
postgres 24627 24623 0 02:06 ? 00:00:00 postgres:proses pencatat
postgres 24631 24623 0 02:06 ? 00:00:00 postgres:proses checkpointer
postgres 24632 24623 0 02:06 ? 00:00:00 postgres:proses penulis
postgres 24633 24623 0 02:06 ? 00:00:00 postgres:proses penulisan awal
postgres 24634 24623 0 02:06 ? 00:00:00 postgres:proses peluncur autovacuum
postgres 24635 24623 0 02:06 ? 00:00:00 postgres:proses pengarsipan
postgres 24636 24623 0 02:06 ? 00:00:00 postgres:proses pengumpul statistik
postgres 24637 24623 0 02:06 ? 00:00:00 postgres:bgworker:Buffer Saver
postgres 24638 24623 11 02:06 ? 00:00:01 postgres:bgworker:Block Reader 2
Dalam log server database saat startup:
-bash-4.1$ more postgresql-2014-06-02_083033. log
LOG:sistem basis data dimatikan pada 02-06-2014 08:13:00 PDT
LOG:memulai proses pekerja latar belakang "Buffer Saver"
LOG:sistem basis data siap diterima koneksi
LOG:peluncur autovacuum dimulaiSejak pg_hibernator pertama kali dimainkan, Anda dapat melihat dua proses dan juga log dengan beberapa informasi tentang awal "Buffer Saver". Sekarang, mari kita lakukan pemanasan awal relasi 'foo' dan restart server, kemudian periksa status buffer apakah pg_hibernator mengisi buffer kembali ke tempat sebelumnya.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Ketik "bantuan" untuk bantuan.
postgres=# pilih pg_prewarm('foo');
pg_prewarm
------------
113278
(1 baris)
--pg_buffercache keluaran kueri
ganti nama | buffer
---------+---------
foo | 113278
(1 baris)
postgres=# q
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch /pg/data_10407 stop
menunggu server dimatikan.... selesai
server dihentikan
-bash-4.1$ ls -l $PGDATA/pg_hibernator/
total 12
-rw------- 1 postgres postgres 160 Jun 3 01:41 1.global.save
-rw------- 1 postgres postgres 915 Jun 3 01 :41 2.postgres.save
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 mulai
server mulaiKami telah me-restart server database, mari kita periksa log
-bash-4.1$ more postgresql-2014-06-03_020601.log
LOG:sistem database dimatikan pada 03-06-2014 02:05:57 PDT
LOG:memulai pekerja latar belakang proses "Buffer Saver"
LOG:sistem database siap menerima koneksi
LOG:peluncur autovacuum dimulai
LOG:mendaftarkan pekerja latar belakang "Block Reader 2"
LOG:memulai pekerja latar belakang proses "Pembaca Blok 2"
LOG:Pembaca Blok 2:dipulihkan 113433 blok
LOG:Pembaca Blok 2:semua blok berhasil dibaca
LOG:proses pekerja:Pembaca Blok 2 (PID 24638) keluar dengan kode keluar 1
LOG:membatalkan pendaftaran pekerja latar belakang "Block Reader 2"
LOG:mendaftarkan pekerja latar belakang "Block Reader 1"
LOG:memulai proses pekerja latar belakang "Block Reader 1"
LOG:Pembaca Blok 1:memulihkan 20 blok
LOG:Pembaca Blok 1:semua blok berhasil dibaca
LOG:proses pekerja:Pembaca Blok 1 (PID 24664) keluar dengan kode keluar 1
LOG :membatalkan pendaftaran pekerja latar belakang "Block Read er 1"Jadi, "Buffer Reader" telah memulihkan blok 113433 + 20, di mana 113278 milik relasi 'foo'. Bagus, mari terhubung dan melihat.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Ketik "bantuan" untuk bantuan.
--pg_buffercache keluaran kueri
relname | buffer
---------+---------
foo | 113278
(1 baris)Keren… pg_hibernator telah mengembalikan kondisi cache yang dihangatkan tanpa campur tangan DBA.
Hal baik lainnya tentang pg_hibernator, standby yang baru dibuat dapat memiliki konten buffer bersama yang sama dengan master, sehingga standby dapat mulai melayani kueri dengan kecepatan penuh. Untuk melakukan latihan ini, saat mengambil cadangan direktori $PGDATA, saya telah meneruskan SIGTERM ke proses “Buffer Saver” sehingga ia menulis konten shared_buffers status saat ini ke disk(direktori $PGDATA/pg_hibernator) dan kemudian diikuti dengan setup standby.
postgres 24637 24623 0 02:06 ? 00:00:00 postgres:bgworker:Buffer Saver
postgres 24653 15179 0 02:06 ? 00:00:01 postgres:proses streaming penerima wal 1/6A000A10
postgres 24654 24623 0 02:06 ? 00:00:00 postgres:proses pengirim wal postgres ::1(65011) streaming 1/6A000A10Setelah penyiapan, budak saya memulai dengan konten utama yang sama
-bash-4.1$ psql -p 10477
psql (9.4beta1)
Ketik "bantuan" untuk bantuan.
postgres=# pilih pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 baris)
--pg_buffercache keluaran kueri
relname | buffer
---------+---------
foo | 113278
(1 baris)Terima kasih kepada kedua penulis untuk ekstensi luar biasa tentang caching.