Apa yang terjadi di pos pemeriksaan PostgreSQL?

22

Inilah bagian dari log pos pemeriksaan saya:

2014-03-26 11:51:29.341 CDT,,,18682,,532854fc.48fa,4985,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 15047 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 30 recycled; write=68.980 s, sync=1.542 s, total=70.548 s; sync files=925, longest=0.216 s, average=0.001 s",,,,,,,,,""
2014-03-26 11:56:05.430 CDT,,,18682,,532854fc.48fa,4987,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 16774 buffers (1.6%); 0 transaction log file(s) added, 0 removed, 31 recycled; write=72.542 s, sync=17.164 s, total=89.733 s; sync files=885, longest=3.812 s, average=0.019 s",,,,,,,,,""
2014-03-26 12:01:21.650 CDT,,,18682,,532854fc.48fa,4989,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 14436 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 33 recycled; write=122.350 s, sync=5.212 s, total=127.676 s; sync files=924, longest=3.740 s, average=0.005 s",,,,,,,,,""
2014-03-26 12:06:25.028 CDT,,,18682,,532854fc.48fa,4991,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 13277 buffers (1.3%); 0 transaction log file(s) added, 0 removed, 29 recycled; write=126.217 s, sync=5.733 s, total=131.991 s; sync files=894, longest=1.859 s, average=0.006 s",,,,,,,,,""
2014-03-26 12:10:41.958 CDT,,,18682,,532854fc.48fa,4993,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 20765 buffers (2.0%); 0 transaction log file(s) added, 0 removed, 28 recycled; write=88.015 s, sync=10.818 s, total=98.872 s; sync files=881, longest=2.690 s, average=0.012 s",,,,,,,,,""

Saya perhatikan bahwa kadang-kadang basis data kami sangat lambat - Anda dapat melihat sejumlah besar kueri pendek yang biasanya macet lebih lama dari sekarang. Ini terjadi secara teratur tanpa penyebab yang jelas.

Pertanyaan: Bisakah pos pemeriksaan menyebabkan ini? Apa yang terjadi pada tahap pemeriksaan "sinkronisasi"?

Konrad Garus
sumber

Jawaban:

32

Selama operasinya, PostgreSQL mencatat perubahan pada file log transaksi, tetapi itu tidak langsung menyiram mereka ke tabel database aktual. Biasanya hanya menyimpan perubahan dalam memori, dan mengembalikannya dari memori ketika diminta, kecuali RAM mulai penuh dan harus menuliskannya.

Ini berarti bahwa jika crash, tabel di disk tidak akan up to date. Itu harus memutar ulang log transaksi, menerapkan perubahan pada tabel pada-disk, sebelum dapat memulai kembali. Itu bisa memakan waktu cukup lama untuk database yang besar dan sibuk.

Karena alasan itu, dan agar log transaksi tidak terus tumbuh selamanya, PostgreSQL secara berkala melakukan pos pemeriksaan di mana ia memastikan bahwa DB berada dalam kondisi bersih. Itu mem-flush semua perubahan yang tertunda ke disk dan mendaur ulang log transaksi yang digunakan untuk menyimpan catatan pemulihan kerusakan dari perubahan.

Siram ini terjadi dalam dua fase:

  • Buffer write()kotor shared_bufferske meja; dan
  • fsync() file yang terkena untuk memastikan perubahan benar-benar memukul disk

Keduanya dapat meningkatkan disk I / O load. Kontensi yang disebabkan oleh penulisan ini dapat memperlambat pembacaan, dan juga dapat memperlambat pembilasan segmen WAL yang diperlukan untuk melakukan transaksi.

Ini merupakan tantangan yang sudah berlangsung lama, tetapi semakin buruk karena kita melihat sistem dengan semakin banyak RAM sehingga mereka dapat buffer lebih banyak data dan membutuhkan waktu lebih lama untuk menuliskannya. Ada diskusi antara komunitas Linux dan PostgreSQL tentang bagaimana menangani hal ini saat ini, seperti yang dibahas dalam artikel LWN.net ini . (LWN.net tidak akan dapat terus menulis karya hebat semacam ini jika orang tidak berlangganan. Saya adalah pelanggan dan membagikan tautan ini karena ini berguna dan informatif. Silakan pertimbangkan berlangganan jika Anda ingin melihat lebih banyak dari ini. semacam itu.)

Hal utama yang dapat Anda lakukan untuk mengurangi dampak pos pemeriksaan saat ini adalah menyebarkan kegiatan pos pemeriksaan dengan meningkatkan checkpoint_completion_targetsehingga lebih banyak data telah ditulis pada saat pos pemeriksaan terakhir tiba. Ini memiliki biaya, meskipun - jika Anda memperbarui halaman (katakanlah) sepuluh kali, itu mungkin ditulis ke disk beberapa kali sebelum pos pemeriksaan dengan target penyelesaian tinggi, meskipun itu hanya harus ditulis sekali untuk keamanan kecelakaan. Target penyelesaian yang lebih tinggi menghasilkan pola I / O yang lebih halus tetapi I / O yang lebih menyeluruh.

Hal lain yang dapat Anda lakukan untuk membantu adalah memberi tahu sistem operasi Anda untuk segera mulai menulis data ketika buffered menulis. Ini seperti sisi pengaturan kernel checkpoint_completion_targetdan memiliki trade-off yang sama. Lihat linux dokumentasi vm , khususnya dirty_background_bytes, dirty_background_ratio, dirty_expire_centisecs.

Craig Ringer
sumber
Penulisan ini tersebar dalam waktu yang lama dan saya tidak berpikir itu menyebabkan masalah. Bagaimana dengan sinkronisasi, apakah itu semacam operasi penghenti dunia?
Konrad Garus
@KonradGarus Sinkronisasi seharusnya bukan jenis operasi yang menghentikan dunia, tetapi sering kali memang demikian. Baca artikel yang saya tautkan di atas, ini adalah ringkasan yang sangat tepat waktu dan berguna dari masalah, meskipun dari sudut pandang yang cukup teknis. Versi singkatnya adalah "fsync () di Linux cenderung untuk benar-benar membuang kinerja I / O bersamaan dengan fsync ()". Anda dapat mengurangi itu dengan opsi tuning yang tercantum di atas, untuk mengurangi jumlah yang harus dihapus oleh fsync.
Craig Ringer
1

Membilas buffer sistem file OS kotor yang disebabkan oleh melebihi dirty_bytesatau dirty_ratio merupakan operasi pemblokiran latar depan!

The tunables kernel dirty_bytes, dirty_background_bytes, dirty_ratio, dirty_background_ratiodan dirty_centisecskontrol disiram kotor buffer sistem OS file ke disk. dirty_bytesadalah ambang dalam byte, dirty_ratioadalah ambang sebagai rasio total memori. dirty_background_bytesdan dirty_background_ratioambang yang serupa, tetapi pembilasan terjadi di latar belakang dan tidak memblokir operasi baca / tulis lainnya hingga selesai. dirty_centisecsadalah berapa banyak centisecond yang dapat dilewati sebelum flush dimulai.

Baru-baru ini standar untuk merdu ini diturunkan di Linux, karena ukuran memori untuk mesin modern telah meningkat secara dramatis. Bahkan rasio 5 dan 10% untuk dirty_background_ratiodan dirty_ratiopada mesin 256GB dapat membanjiri sistem I / O.

Menyetel dirty_background_bytesatau dirty_background_ratiomulai menyiram buffer kotor di latar belakang itu sulit. Untungnya Anda dapat menyetel pengaturan ini tanpa harus menghentikan PostgreSQL atau tuan rumah dengan menggemakan nilai baru ke file yang sesuai:

$ sudo echo [int value of bytes] > /proc/sys/vm/dirty_background_bytes

misalnya untuk mengatur jumlah byte yang kotor untuk memicu flush latar belakang. Jika Anda menggunakan baterai yang didukung, kapasitor yang didukung, atau memori flash card RAID (Anda tidak ingin menyimpan data Anda dalam kasus kecelakaan, bukan?) Mulai dengan tuning dirty_background_bytesuntuk 1/2 menulis cache ukuran buffer dan dirty_bytesuntuk 3/4 ukuran itu. Pantau profil I / O Anda dengan iostats dan jika Anda masih melihat masalah latensi itu berarti beban penulisan basis data Anda masih membanjiri flush cache buffer file. Perkecil nilainya hingga latensi membaik atau pertimbangkan untuk meningkatkan subsistem I / O Anda. Kartu FusionIO dan SSD adalah dua kemungkinan untuk throughput I / O yang ekstrem.

Semoga berhasil!

bobl
sumber
Komentar Anda tentang data "kotor" adalah poin yang relevan untuk kelambatan. Pada dasarnya: semakin besar rasio kotor, semakin banyak buffer dialokasikan untuk data kotor sebelum membilas masuk. Dengan demikian, meminimalkan penundaan pembilasan berarti meningkatkan buffer kotor, atau meningkatkan waktu data kotor dapat tetap berada dalam memori.
Peter Teoh