Postgres berisi cakrawala peristiwa yang bergerak, yang berlaku sekitar 2 miliar transaksi di depan atau di belakang id transaksi saat ini. Transaksi hingga 2 miliar lebih awal atau lebih dari 2 miliar di belakang id transaksi saat ini dianggap di masa mendatang, dan dengan demikian tidak akan terlihat oleh transaksi saat ini.
Postgres menghindari kehilangan data bencana ini dengan secara khusus menandai baris lama sehingga di mana pun mereka berada dalam kaitannya dengan id transaksi saat ini, baris tersebut akan terlihat.
Pembekuan adalah proses menandai tupel hidup lama (yaitu baris database) sehingga mereka tidak terlindas oleh cakrawala peristiwa bergerak yang sebaliknya akan membuatnya tampak di masa depan. Hal ini berbeda dengan penyedot debu, yang membebaskan ruang yang digunakan oleh tupel mati lama yang tidak lagi terlihat oleh transaksi apa pun.
Kedua proses dikelola oleh vakum.
Ada sejumlah pengaturan yang mengatur bagaimana pembekuan dilakukan.
Pertama, vacuum_freeze_min_age
mengatur apakah tupel akan dibekukan atau tidak saat vakum sedang melihat halaman untuk melihat apakah ada tupel mati yang dapat dibersihkan. Tuple yang lebih lama dari vacuum_freeze_min_age
akan dibekukan dalam kasus ini. Menyetel rendah ini berarti akan ada lebih sedikit pekerjaan yang harus dilakukan nanti, tetapi dengan kemungkinan biaya usaha ekstra baik dalam aktivitas CPU dan IO atau WAL. Umumnya Anda mungkin ingin set ini setidaknya untuk beberapa jam transaksi. Katakanlah Anda mengharapkan untuk melakukan hingga 2000 transaksi per detik sebagai tarif berkelanjutan. 2000 TPS adalah 7,2 juta transaksi per jam. Jadi pengaturan yang cukup agresif untuk kasus ini bisa dikatakan 20m. Pengaturan default adalah 50m. Demikian pula untuk vacuum_multixact_freeze_min_age
. Perhatikan bahwa penghitung transaksi_id dan multixid bersifat independen – Anda harus melacak keduanya.
Kedua, ada vacuum_freeze_table_age
dan vacuum_multixact_freeze_table_age
. Pengaturan ini mengatur kapan autovacuum tidak hanya akan melihat halaman yang mungkin memiliki baris mati, tetapi halaman apa pun yang mungkin memiliki baris yang tidak dibekukan. Default untuk pengaturan ini adalah 150m. Jika Anda telah mengurangi vacuum_freeze_min_age
cukup, dalam banyak kasus ruang hampa yang lebih agresif ini akan memiliki sedikit atau tidak ada pekerjaan yang harus dilakukan. Bagaimanapun, proses ini tidak sesibuk dulu, karena Postgres versi modern (9.6 dan lebih tinggi) menyimpan peta halaman tempat semua tupel dibekukan, dan hanya mengunjungi halaman yang tidak semuanya dibekukan. Artinya, ini bukan lagi pemindaian tabel penuh.
Terakhir ada autovacuum_freeze_max_age
. Jika terakhir kali tabel dipindai sepenuhnya untuk baris yang tidak dibekukan lebih dari ini banyak transaksi yang lalu, autovacuum akan memulai vakum anti-wraparound di atas meja. Standarnya adalah 200m. Demikian pula untuk autovacuum_multixact_freeze_max_age
yang standarnya adalah 400m. Ini adalah sesuatu yang benar-benar ingin Anda hindari. Ada dua hal yang bisa dilakukan. Pertama, sangat umum untuk meningkatkan pengaturan ini menjadi sekitar 1 miliar, untuk memberi Anda lebih banyak ruang kepala, terutama pada sistem yang merupakan konsumen transaksi yang berat. Anda dapat membuatnya lebih banyak tetapi Anda ingin memiliki banyak ruang transaksi antara tupel tertua Anda dan cakrawala peristiwa. Kedua, penting untuk memantau sistem Anda dan mengambil tindakan perbaikan sebelum database mengalami hal ini. Tindakan perbaikan ini sering kali mencakup penyedotan debu manual.
Satu masalah yang dapat terjadi adalah di mana Anda memiliki DDL yang menyebabkan autovacuum normal (yaitu tidak anti-wraparound) membatalkan dirinya sendiri. Jika Anda melakukan ini pada akhirnya, Anda akan mendapatkan vakum anti-wraparound yang dipaksakan, dan DDL apa pun kemudian mengantre di belakang proses vakum, dan itu pada gilirannya memblokir DML lebih lanjut. Pada tahap ini meja Anda secara efektif tidak terbaca sampai vakum selesai. Ini tergantung pada pola penggunaan database Anda, tetapi ini bukan hanya kemungkinan teoretis dan penerapan Postgres serta DBA perlu mempertimbangkannya.
Memantau cluster database Anda sangat penting untuk mengelola ini. Secara khusus Anda perlu memantau datfrozenxid
dan datminmxid
dari setiap database di cluster, dan jika ini terlalu tua, ambil tindakan perbaikan sebelum vakum anti-wraparound diperlukan. Seringkali masalahnya adalah dengan satu atau beberapa tabel dalam database. Yang mana masalahnya dapat ditemukan dengan memeriksa relfrozenxid
dan relminmxid
dari tabel dalam database. age()
dan mxid_age()
fungsi yang berguna untuk mengetahui umur masing-masing id transaksi dan multixid counter.
Pembekuan bukanlah sesuatu yang dapat Anda hindari, ini adalah aktivitas pemeliharaan penting di Postgres yang perlu dikelola secara aktif.