Postmaster menggunakan CPU dan Disk Disk yang berlebihan

9

menggunakan PostgreSQL 9.1.2

Saya melihat penggunaan CPU yang berlebihan dan sejumlah besar penulisan ke disk dari tugas-tugas postmaster. Ini terjadi bahkan ketika aplikasi saya hampir tidak melakukan apa-apa (10s sisipan per MENIT). Namun ada sejumlah koneksi terbuka yang masuk akal.

Saya sudah mencoba menentukan apa yang menyebabkan aplikasi saya ini. Saya cukup pemula dengan postgresql, dan sejauh ini belum sampai ke mana pun. Saya telah mengaktifkan beberapa opsi logging di file config saya, dan melihat koneksi di tabel pg_stat_activity, tetapi semuanya idle. Namun setiap koneksi mengkonsumsi ~ 50% CPU, dan menulis ~ 15M / s ke disk (tidak membaca).

Saya pada dasarnya menggunakan stock postgresql.conf dengan sedikit sekali tweak. Saya menghargai saran atau petunjuk tentang apa yang bisa saya lakukan untuk melacak ini.

Berikut ini contoh apa yang ditunjukkan oleh top / iotop:

Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle

Pembaruan : Banyak penulisan file sepertinya merupakan beberapa file sementara (?) Di direktori $ PG_DATA / base /. Pemahaman saya tentang struktur file di sini adalah bahwa setiap tabel pada dasarnya disimpan sebagai file yang namanya OID dari tabel. Namun, ada berton-ton file yang dinamai tnn_nnnnnnn, dan file-file inilah yang tampaknya selalu ditulis (mungkin ditulis). Untuk apa file-file ini? Ada ~ 4700 file, dan semuanya berukuran 8K:

-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334

Pembaruan : Menjalankan strace pada proses postmaster pada dasarnya menunjukkan banyak hal I / O file:

open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "\0\0\0\0\0\0\0\0\1\0\0\0000\0\360\37\360\37\4 \0\0\0\0b1\5\0\2\0\0\0"..., 8192) = 8192
lseek(18, 0, SEEK_END)                  = 0
close(9)                                = 0
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
close(18)                               = 0
close(9)                                = 0
open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 0
close(9)                                = 0

Pembaruan : Jadi masalah ini sepertinya adalah segala sesuatu yang berkaitan dengan tabel sementara. Kami mengubah pengaturan kami sehingga tabel sementara adalah tabel 'biasa', dan semua aktivitas disk hilang, dan kinerja kembali ke tempat yang saya harapkan. Sekarang, perubahan ini hanyalah tes cepat dan kotor: jika kita benar-benar akan berubah menggunakan tabel biasa, kita memiliki masalah dengan konkurensi, dan pembersihan. Apakah meja sementara benar-benar jahat, atau kita menyalahgunakannya?

Perbarui : Beberapa latar belakang lagi. Saya menggunakan middleware replikasi berbasis pernyataan dikembangkan in-house . Ini cukup matang dan telah digunakan pada sejumlah proyek selama beberapa tahun, tetapi menggunakan MySQL. Kami hanya bekerja dengan PostgreSQL selama satu atau dua tahun terakhir. Kami pada dasarnya menggunakan tabel sementara sebagai bagian dari mekanisme replikasi. Setiap kali koneksi baru dibuat, kami membuat tabel sementara untuk setiap tabel dalam database. Dengan koneksi 10-20 (berumur panjang) dan ~ 50 tabel, ini bisa berjumlah banyak tabel sementara. Semua tabel sementara dibuat dengan:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

Semantik tabel sementara sangat sesuai dengan skema replikasi kami, dan menyederhanakan banyak kode yang harus kami gunakan untuk MySQL, tetapi sepertinya implementasinya juga tidak adil. Dari sedikit riset yang telah saya lakukan, saya tidak berpikir tabel sementara benar-benar dimaksudkan untuk fungsi yang kami gunakan.

Saya bukan ahli dalam-rumah (bahkan tidak dekat) tentang hal ini, hanya pengguna, jadi penjelasan saya mungkin tidak 100% akurat, tapi saya pikir itu cukup dekat.

wolfcastle
sumber
3
Pemahaman Anda agak ketinggalan jaman, jika Anda melihat dokumentasi resmi , Anda akan menemukan bahwa "... untuk hubungan sementara, nama file adalah dari bentuk tBBB_FFF, di mana BBB adalah ID backend dari backend yang membuat file , dan FFF adalah nomor filenode ... "
Milen A. Radev
Wow, itu adalah subsistem I / O disk yang berkinerja baik. Apa yang dikatakan strace tentang apa yang sebenarnya dilakukan para pekerja?
womble
@ MilenA.Radev, jadi sepertinya saya mungkin melakukan sesuatu yang aneh / berlebihan dengan tabel sementara. Ini menarik. Saya memiliki banyak pemicu di tempat yang menggunakan tabel sementara. Saya akan melihat lebih dekat pada ini.
wolfcastle
@ Womble, saya telah memperbarui pertanyaan dengan output dari strace.
wolfcastle
Apakah Anda benar-benar mengalami masalah kinerja?
voretaq7

Jawaban:

1

Konfigurasi PostgreSQL Anda tidak aktif. Ini mencurigakan dari pos awal Anda,

 Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
 Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
 Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

Dari 32GB di server Anda, ~ 25GB gratis tidak termasuk ~ 575MB buffer.

Dari file postgresql.conf Anda,

 shared_buffers = 32MB                   # min 128kB                               
 #temp_buffers = 8MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 #work_mem = 1MB                         # min 64kB
 #maintenance_work_mem = 16MB            # min 1MB
 #max_stack_depth = 2MB   

Saya berasumsi ini adalah database khusus. Jika demikian, ubah ke parameter berikut dan muat ulang,

 shared_buffers = 16GB                   # min 128kB                               
 temp_buffers = 128MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 work_mem = 8MB                         # min 64kB
 maintenance_work_mem = 64MB            # min 1MB
 max_stack_depth = 4MB   

Biarkan saya tahu bagaimana ini mengubah kinerja Anda dan selanjutnya dapat menyetelnya sesuai kebutuhan.

Salam ke tabel yang tidak di-log, jika tabel sementara Anda berisi data sementara yang bersifat sementara dan, seperti yang Anda sebutkan, dibuat di sesi, lebih baik menggunakan tabel yang tidak di-log.

Anda dapat memotong sesi posting tabel Anda jika itu dapat diterima.

Info lebih lanjut di sini - http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

Saya tidak yakin mengapa Anda membutuhkan tabel temporer untuk replikasi. Tidak bisakah Anda menggunakan replikasi streaming PostgreSQL?

Chida
sumber
0

Menggunakan tabel sementara dan memiliki koneksi lama (mungkin pooling koneksi terlibat) dapat menjadi beban jika server Anda tidak siap untuk itu. Satu parameter PostgreSQL yang bisa Anda coba mainkan adalah temp_buffersyang mengontrol RAM yang dialokasikan untuk tabel sementara. Buffer sementara tersebut dialokasikan per koneksi dan nilai default (8MB) mungkin terlalu rendah untuk situs Anda.

Mungkin Anda juga perlu mengubah sedikit perilaku aplikasi klien Anda, tergantung pada bagaimana Anda menggunakan tabel sementara Anda. Ada pertanyaan serupa dengan jawaban yang bagus di Stack Overflow .

Tonin
sumber
Saya harus bertanya kepada pakar di rumah saya apakah kami mencoba menyesuaikan nilai temp_buffers atau tidak (kami mencoba banyak hal berbeda). Pertanyaan yang Anda tanyakan tidak benar-benar berlaku karena kami tidak menggunakan tabel sementara dengan cara itu. Saya telah memperbarui pertanyaan dengan beberapa perincian lebih lanjut.
wolfcastle
Terima kasih atas pembaruan untuk pertanyaan dan untuk file postgresql.conf, itulah yang perlu kita coba tingkatkan pada situasi ini. Saya setuju dengan jawaban @Chida yang sesuai dengan apa yang saya sarankan wrt temp_buffers. Bisakah Anda memberi tahu kami berapa ukuran DB yang Anda coba tiru? Berapa banyak tabel, ukuran rata-rata per tabel dan ukuran total DB?
Tonin
0

Bisakah Anda memposting file postgresql.conf Anda? Postgresql Anda tampaknya kurang optimal.

Bisakah Anda memposting:

  • Jika Anda menggunakan tabel yang belum di-log untuk tabel sementara Anda?

  • Berapa banyak disk dan dalam konfigurasi RAID apa?

Chida
sumber
Saya telah meletakkan file postgresql.conf di sini . Saya percaya Anda tidak bisa membuat tabel yang bersifat sementara DAN tidak dicatat. Ada 6 disk 1TB dalam RAID 1 + 0 (total penyimpanan 3TB)
wolfcastle