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

9

используя 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%, но я думаю, что оно довольно близко.

wolfcastle
источник
3
Ваше понимание немного устарело, если вы посмотрите на официальную документацию , вы обнаружите, что «... для временных отношений имя файла имеет вид tBBB_FFF, где BBB - это внутренний идентификатор сервера, который создал файл , а FFF - номер файла. ... "
Милен А. Радев,
Вау, это хорошо работающая подсистема дискового ввода-вывода. Что говорит Стрейс о том, что на самом деле делают рабочие?
Уомбл
@ MilenA.Radev, похоже, я делаю что-то странное / чрезмерное с временными таблицами. Это интересно. У меня есть много триггеров, которые используют временные таблицы. Я буду смотреть на это поближе.
wolfcastle
@womble, я обновил вопрос с выводом из strace.
wolfcastle
Вы действительно испытываете проблемы с производительностью?
voretaq7

Ответы:

1

Ваша конфигурация 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?

Chida
источник
0

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

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

Tonin
источник
Я должен спросить моего внутреннего эксперта о том, пытались ли мы изменить значение temp_buffers или нет (мы пробовали много разных вещей). Вопрос, на который вы указываете, на самом деле не применим, поскольку мы не используем временные таблицы таким образом. Я обновил вопрос с некоторыми более подробной информацией.
wolfcastle
Спасибо за обновление вопроса и за файл postgresql.conf, это то, что мы должны попытаться улучшить в этой ситуации. Я согласен с ответом @Chida, который согласуется с тем, что я предложил в отношении temp_buffers. Можете ли вы также сказать нам, какой размер БД вы пытаетесь реплицировать? Сколько таблиц, средний размер таблицы и общий размер БД?
Тонин
0

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

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

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

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

Chida
источник
Я поместил файл postgresql.conf здесь . Я считаю, что вы не можете создать таблицу, которая является одновременно временной и незагруженной. В RAID 1 + 0 (3 ТБ общего хранилища) 6 дисков по 1 ТБ
wolfcastle