Назад | Перейти на главную страницу

Postmaster использует чрезмерное количество операций записи на ЦП и диск

с использованием PostgreSQL 9.1.2

Я наблюдаю чрезмерную загрузку процессора и большое количество операций записи на диск из задач postmaster. Это происходит даже тогда, когда мое приложение почти ничего не делает (10 секунд вставок в МИНУТУ). Однако открыто разумное количество подключений.

Я пытался определить, что в моем приложении вызывает это. Я новичок в postgresql и пока ничего не добился. Я включил некоторые параметры ведения журнала в своем конфигурационном файле и посмотрел на соединения в таблице pg_stat_activity, но все они неактивны. Тем не менее, каждое соединение потребляет ~ 50% ЦП и записывает на диск ~ 15 Мбит / с (ничего не читает).

Я в основном использую стандартный postgresql.conf с очень небольшими изменениями. Буду признателен за любые советы или подсказки о том, что я могу сделать, чтобы отследить это.

Вот пример того, что мне показывает 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

Обновить: Большая часть файлов записывается в некоторые временные (?) Файлы в каталоге $ PG_DATA / base /. Мое понимание файловой структуры здесь заключается в том, что каждая таблица в основном хранится как файл, имя которого является OID таблицы. Однако существует множество файлов с именами tnn_nnnnnnn, и кажется, что именно эти файлы постоянно записываются (возможно, перезаписываются). Для чего нужны эти файлы? Есть ~ 4700 файлов, все размером 8 КБ:

-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

Обновить: Запуск strace в процессах postmaster в основном показывает много файлового ввода-вывода:

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

Обновить: Итак, эта проблема, похоже, связана с временными таблицами. Мы изменили нашу настройку, так что временные таблицы являются «обычными» таблицами, и вся дисковая активность исчезла, а производительность вернулась к той, которой я ожидал. Теперь это изменение было просто быстрой и грязной проверкой: если мы действительно собираемся использовать обычные таблицы, у нас есть проблемы с параллелизмом и очисткой. Неужели временные таблицы такие злые, или мы ими злоупотребляем?

Обновить: Еще немного предыстории. Я пользуюсь собственной разработкой ПО промежуточного слоя репликации на основе операторов. Он довольно зрелый и использовался в ряде проектов в течение нескольких лет, но с использованием MySQL. Мы работаем с PostgreSQL только последние год или два. По сути, мы использовали временные таблицы как часть механизма репликации. Каждый раз, когда устанавливается новое соединение, мы создаем временную таблицу для каждой таблицы в базе данных. С 10-20 (долгоживущими) соединениями и ~ 50 таблицами это может составить множество временных таблиц. Все временные таблицы были созданы с помощью:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

Семантика временных таблиц очень хорошо согласуется с нашей схемой репликации и упрощает большую часть кода, который мы должны были использовать для MySQL, но похоже, что реализация также была нечестной. Судя по тому небольшому исследованию, которое я провел, я не думаю, что временные таблицы действительно предназначались для той функции, для которой мы их использовали.

Я не являюсь штатным экспертом (даже близко) по этому вопросу, я просто пользуюсь им, поэтому мое объяснение может быть не на 100% точным, но я думаю, что оно довольно близко.

Ваша конфигурация PostgreSQL не работает. Это было подозрительно из вашего первоначального сообщения,

 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

Из 32 ГБ на вашем сервере ~ 25 ГБ свободно, не считая ~ 575 МБ буфера.

Из вашего файла postgresql.conf,

 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   

Я предполагаю, что это выделенная база данных. Если да, измените его на следующие параметры и перезагрузите / перезапустите,

 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   

Сообщите мне, как это повлияет на вашу производительность, и дайте мне возможность настроить ее по мере необходимости.

Что касается незарегистрированных таблиц, если ваши временные таблицы содержат временные данные, которые являются эфемерными и, как вы упомянули, создаются во время сеанса, лучше использовать незарегистрированные таблицы.

Вы можете усечь свои таблицы после сеанса, если это приемлемо.

Подробнее здесь - http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

Я не уверен, зачем вам временные таблицы для репликации. Разве вы не можете использовать потоковую репликацию PostgreSQL?

Не могли бы вы опубликовать свой файл postgresql.conf? Ваш postgresql, похоже, значительно не оптимизирован.

Не могли бы вы также опубликовать:

  • Если вы используете незарегистрированные таблицы для временных таблиц?

  • Сколько дисков и в какой конфигурации RAID?

Использование временных таблиц и наличие длительных подключений (вероятно, задействован пул подключений) может стать обузой, если ваш сервер к этому не подготовлен. Один из параметров PostgreSQL, с которым вы можете попробовать, - это temp_buffers который управляет ОЗУ, выделенным для временных таблиц. Эти временные буферы выделяются для каждого соединения, и значение по умолчанию (8 МБ), вероятно, слишком мало для вашего сайта.

Возможно, вам также нужно немного изменить поведение вашего клиентского приложения, в зависимости от того, как вы используете свои временные таблицы. Есть аналогичный вопрос с хороший ответ на переполнение стека.