Pull to refresh
93
0.1

PostgreSQL DBA

Send message

Специально придуманные ИБП, ага, как бы не так... В реальной жизни:
один ИБП просто вырубает нагрузку "а что, у вас какая-о мелочь там, а мы green!!"
другой не включает нагрузку после возвращения электроснабжения пока не ткнёшь кнопку
третий именно что не успевает переключиться на батарею, роутер ребутается
и попробуй это всё выяснить не экспериментально

О, ключевое слово Pass-Through Charging для поиска это полезно. У меня роутер от type C питается, иногда думаю не заменить ли UPS на повербанк, но непонятно какие смогут работать.

Опять чатгпт писал?
Комментарии к pg_stat_statements.track и track_activity_query_size просто неверны, а требуемый для активации pg_stat_statements shared_preload_libraries вовсе не упомянут.
total_time в pg_stat_statements давно уже нет, во время добавления total_plan_time (если включен pg_stat_statements.track_planning) был переименован в total_exec_time.

wal_level = archive давным-давно deprecated псевдоним для wal_level = replica

Слот репликации - это механизм, который используется для передачи WAL записей от мастера к реплике без необходимости активного участия реплики.

неверно. Слот физической репликации - это механизм, гарантирующий что у вас переполнится диск на мастере, но не будут удалены WAL, о получении которых ещё не отчиталась реплика.
Соответственно, вы вообще никак не пояснили, зачем вам вообще слот репликации. (хинт: он просто не нужен для pitr)

Где вы нашли синтаксис ALTER SLOT для меня, конечно, загадка. Нет такой синтаксической конструкции даже в pg17.

Ну и последнее, но самое важное: вся статья исключительно по EOL версиям postgresql и не подходит для более новых. pg_xlog* функций не существует с pg10, а чтение файла с именем recovery.conf удалил лично я начиная с postgresql 12. Это конечно объясняет пример с archive wal_level, зато вызывает вопросы к "онлайн-курсу"

Да, wal_compression вполне заметно работает, даже при том что только на full page image записях применяется. Сжатие производится до записи WAL как такового, а потому снижает не только объёмы передачи потоковой репликации, но и IO тоже. И к архиву тоже соответственно применяется.

А вот если помимо wal_compression сжимать весь сегмент чем-то ещё сверху - то эффект куда сильнее. Вроде такого

melkij@melkij:/tmp/z$ du -hs *
17M	000000010000003500000034
3,3M	000000010000003500000034.gz
2,2M	000000010000003500000034.zst

Лидер временно может хранить WAL-ов больше, чем указано в параметре wal_keep_size (например, из-за долгой транзакции)

Мастер может в любой конфигурации хранить WAL'ов больше чем указано где-либо потому что ограничения на максимальный объём WAL просто нет.
И нет, wal_keep_size не имеет никакого отношения к долгим транзакциям. У нас REDO, не волнует возраст транзакций ни для crash recovery ни для удержания WAL, нас волнует LSN который записали при чекпойнте и соответственно откуда стартовать recovery. А уже при crash recovery смотрим, встретили ли commit запись в WAL или нет.

Вот то, что wal_keep_size держит постоянно занятый объём, я, впрочем, и вовсе как недостаток не рассматриваю - это вполне неплохой удобный резерв наравне с reserved space в ext4. Надо освободить место - оговариваем, что тогда могут отвалиться дальние/медленные реплики. Зато когда медленные реплики действительно отстают - у нас не начинает исчезать свободное место.

Я понимаю, что если тащить WAL-ы из той же Москвы в Новосибирск, то идея с архивной репликацией быстро умрет :)

Я бы кстати наоборот ожидал что на фиговой сети file shipping репликация будет менее проблемная. WAL'ы в виде файликов неплохо сжимаются и сжатие wal просто добавить для архива (по-моему, это вообще дефолтный режим в wal-g). А вот streaming репликация гоняет несжатые данные. При том, потоковая репликация ходит строго одним TCP коннектом. Если нет своих сетевых инженеров для тюнинга сетевого стека, то кучка маленьких параллельных TCP сессий на нестабильной сети наверняка будут работать лучше чем одно долгоживущее.

Ну и в плюсы репликации через архив можно добавить, что для этого способа не надо прорубать сетевое окно на подключение до рабочих баз через всевозможные VPN и файрволы по пути. Базу можно изолировать в закрытом сетевом контуре, куда извне не подключиться.
Плюс гибкость выбора транспортировки WAL, хоть по RFC 1149 кидать.

Как обычно, какую задачу решаем?

Если вам нужна гарантия, что все WAL сохранены где-то ещё - то начать нужно с вопроса, что вы хотите что бы делала база когда это невозможно. Ну вот буквально, транзакция хочет сделать insert данных. Что делать базе? Разрешить выполнить запись сразу и закоммитить? Всё, тут мы уже нарушили гарантию доставки WAL. У нас есть кусочек WAL, который существует только локально на этой базе и ещё не был никуда скопирован. Для этой задачи нужна синхронная репликация. При том, иметь в виду, что insert в postgresql выполнен будет в любом случае при активной синхронной репликации, синхронная репликация гарантирует что ответ базы "commit выполнен" будет получен после доставки WAL на указанную конфигурацию синхронных реплик. При проблемах с синхронной репликацией останавливается запись данных, но раз просили гарантию сохранности - то вот она цена.

Хотим чтобы реплика могла догнать после существенного отставания репликации?
гарантированно? слот репликации без ограничения, либо архив WAL если он очищается с учётом отставания этой реплики. Хочу обратить внимание, что если archive_command перестаёт работать - то база будет накапливать WAL безгранично, подобно слотам репликации max_slot_wal_keep_size. Зато скорей всего под архив WAL получится выделить куда более вместительное и более дешёвое хранилище. Цена той гарантии, что реплика догонит - потенциально неограниченный расход места на хранение WAL.
после разумного объёма отставания? wal_keep_size либо слот репликации с max_slot_wal_keep_size, либо архив WAL если тот очищается независимо от отставания реплики

Но вообще архив WAL обычно заводят когда нужен point-in-time-recovery, а не для репликации. И это другая задача. А потом уже, раз всё равно пишем архив WAL, - то можно и задействовать restore_command чтобы из него подтягивать недостающие WAL для отстающих реплик, попутно.

В большинстве production систем действительно лучше потерять реплику и переналить заново, чем уронить мастер с переполнением диска. Поэтому мы почти всегда используем только wal_keep_size. Если реплика отстала до requested WAL segment ... has already been removed и ничего не могли сделать после того как мониторинг сказал что реплика отстаёт - то переналить заново. Зато не потеряли мастер.

restore_command, кстати, имеет одно не очень явно задокументированное свойство: он имеет безусловный приоритет над WAL уже сохранёнными в pg_wal. То есть даже если у вас все WAL есть локально у базы во время старта, то всё равно они будут заново читаться из архива. Поэтому если у вас архив wal не очень быстрый на чтение - то restore_command будет замедлять все рестарты баз.

гхм, а что за фс в 2023 не поддерживают trim?

а можно не "не поддерживает", а "не использует по умолчанию"? Тогда - большинство. Для большинства файловый систем опция discard в linux выключена по-умолчанию. См. https://wiki.archlinux.org/title/Solid_state_drive со ссылками на rhel/ubuntu/debian и вовсе ядро linux с целым списком девайсов с серьёзными ошибками в прошивках, из-за которых для них персонально отключают часть функциональности.

Вместо discard дистрибьютивы обычно делают в кроне или по systemd таймеру вызов fstrim раз в неделю или около того.

Хочу напомнить, что в отличии от распространённых практик другого софта, для mysql х.0 релиз даже изначально не планируется как General Availability релиз, и это даже не бета. Это просто Development Milestone "мы хотим чего-нибудь показать". До General Availability ещё пара лет.
Не вижу, чтобы для 8.1 эта политика менялась.

Для нормального использования, конечно, лучше всего TLC

ну вот лет через несколько точно так же и про QLC говорить будут, как про TLC лет 5 назад было "кому нужен одноразовый SSD"
Уже и PLC flash из лабораторий выходит, как раз.

так вам просто некуда писать после быстрого заполнения четверти диска для QLC либо трети диска при TLC. Всё, ёмкость кончилась, если до сих пор писали 1 бит в ячейку. Несколько процентов избыточности флеша вам дадут, но ставить 2тб флеша и продавать как 1тб не будут точно.
А дальше попадаем на серьёзный штраф времени на erase блока, который исключает всякий смысл неполной записи ячейки. По-моему, возможность ускориться есть только для такого псевдо SLC однобитового режима, или же уже нет смысла (а то и возможности) извращаться и нужно писать номинальное количество бит на ячейку.

Как будет падать график - больше от прошивки контроллера зависит, чем от чего-то другого.

Неа, одинаковые там чипы. Нюанса два:

  • при записи данных во flash это не просто взяли и записали байтики (write), а писать можно только в подготовленные, очищенные ячейки (erase). И вот erase - это весьма долго по сравнению с собственно записью, а ещё может выполняться только блоками относительно физической структуры NAND.

  • как пишется TLC (да и QLC тоже). Это не взяли битики и записали за один раз все 3 (4 у qlc) битики в ячейку. Процесс многостадийный. Следовательно - более медленный. При этом, есть физическая возможность прерваться после записи одного бита в ячейку, затратив при этом соответственно меньше времени (сильно меньше времени).

Ну и вот она, возможность в бенчмарках показать какие-нибудь красивые цифры. Сообщить (discard) накопителю, что данных на нём нет, дать ему время поработать над erase своих ячеек своего флеша. Дать нагрузку на запись, контроллер делает фокус с записью только одного бита в ячейку. Пока есть свободные ячейки (и не дошли до софтовых ограничений в прошивке, например, использовать только такую-то ёмкость в таком стиле) - получаем качественное ускорение записи. Маркетинг в восторге.
А вот как свободные ячейки кончаются, но запись так и не прерывали - скорость записи резко падает. Контроллеру теперь нужно освобождать место на флеше. Читать записанное ранее, переписывать в полноценном TLC режиме, делать erase освобождённых ячеек, писать, в конце концов, то что продолжает требовать записать ОС.

Зато если запись случается нечастыми такими скачками, ОС сообщает об удалении данных (TRIM), а пользователь не забивает диск к 100% - то всё равно остаётся вполне хорошее ускорение для большинства пользователей. Это делают практически все десктопные модели, ориентация на нечастые спринтерские забеги, но не под постоянную запись. Ну а то что маркетинг об этом, разумеется, не скажет - как будто что-то неожиданное.

Да и многие серверные делают так же, вполне себе состоялось деление на разные семейства SSD под Read Intensive (см. выше) или же write-intensive (запись будет плюс-минус стабильна под постоянной пишущей нагрузкой, но дорого).

ну, на самом деле действительно нетипично на сервере ставить систему, которой осталось пара недель до EOL. Вообще не LTS убунта на сервере настораживает.

performance testing is the state of art (c)

железо:
поизучать наработки годов этак 2006-2012 overclokers, fcenter, ixbt и других грандов былых времён по части тестовых стендов и методик сравнения различающегося железа. Особенно методики тестирования i7 920 как первого 3-канальника. Какие шишки на нём собрали, как сглаживали эффекты различия объёма, как тестировали изменение числа каналов памяти.

одну и ту же пару дисков переставлять физически в каждый сервер. В начале короткий fio минут на 5 для детектирования аномалий, различия результатов теста между серверами, понятное дело, должно быть минимально. Если это не так - то искать причину.
желательно использовать одну и ту же коллекцию модулей памяти, с проверкой что они стартуют в одинаковом режиме частота&тайминги среди всех участников
влияние разной конфигурации заполнения слотов памяти - идея для тестирования платформы в отдельности, на самом деле. Это лично мне, кстати, действительно интересно - имеет ли значение число каналов памяти кроме как для увеличения максимального объёма памяти. Максимум памяти в реальности не столь актуален для СУБД, даже террабайт RAM очень мало кто ставит, а вот есть ли смысл просить именно задействовать каналы памяти, а не добить до нужного объёма теми модулями что под рукой нашлись?
на разных платформах соответственно дать настолько близкую разбивку модулей по каналам и сокетам насколько получится, различия задокументировать
контроль температуры и троттлинга на протяжении тестов (для серверов тоже не шутка, да, была у нас машинка в ovh (вполне серверный xeon D-2141I, не десктоп), которая под нагрузкой перегревалась и сбрасывала частоту CPU втрое)

ОС:
NUMA. NUMA это проблема. Честно не знаю как сглаживать его артефакты кроме как переключением всей системы в interleave либо сознательно через numactl тестировать только половину сервера. Особое счастье с EPYC'ами, где по 4 NUMA ноды бывает даже в одном сокете.
cpu performance mode. В реальности под базой данных CPU решает выходить из powersafe и поднимать частоту до рабочей довольно поздно (мой опыт - это разница в полтора раза по графикам среднего времени выполнения запросов от веба). Но главное для теста - непостоянно. performance mode нам тоже не даст постоянную рабочую частоту, но куда лучше чем powersafe.

postgres
ох (с)
сейчас я упомянут даже в списках разработчиков postgresql, но понимания как корректно тестировать его производительность стало даже меньше, чем когда я про него даже не знал =)
pgbech - ну, это pgbench. Чистая синтетика, довольно бесполезная сама по себе. А вот что-то полезное моделировать... (за это DBA не любят детей ораклового маркетинга "у нас 10k tps, справится postgres?" - каких именно транзакций-то?)
Разглядел, кстати, затаивщийся в опциях scale factor, с первого раза не признал его в краткой форме. То есть примерно 150гб рабочий набор у вас на начало теста. Боюсь, что на самом деле протестировали менеджер локов и реализацию spinlock нежели собственно производительность запросов: все операции над данными postgres выполняет только в shared_buffers, а он в дефолте аж целых 128МБ. Получается конкурентные процессы активно дрались между собой, чтобы скопировать из page cache системного в shared buffers нужный именно этому процессу блок (памяти явно достаточно во всех случаях, чтобы реально на диск только писать, но не читать). А вот со spinlock'ами на ARM у postgresql действительно не всё хорошо: https://www.postgresql.org/message-id/flat/CAB10pyamDkTFWU_BVGeEVmkc8%3DEhgCjr6QBk02SCdJtKpHkdFw%40mail.gmail.com Скорей всего так до сих пор не оптимальный машинный код и компилируется в GCC для ARM.
Поскольку тестировать хотим CPU, в меньшей мере память и не хотим диск, то стоит поставить shared_buffers гигабайт в 180 (хотя на сотне процессов уже может отвалиться вот тот конфиг на 192гб памяти с OOM), synchronous_commit = off. huge_pages = on на таком объёме памяти уже точно нужен (соответственно в ОС тоже выделить huge pages)

PS: я понимаю почему выбрана модель "специально ничего не настраиваем", в этом есть смысл, но по моему опыту shared_buffers всё-таки пользователи крутят чуть менее чем всегда, думаю полезнее чем дефолтные 128мб тестировать будет.

Не всегда, да. Но вы это не указали в статье. Поискал внимательнее, в описании конфигурации вы вообще никак не упоминаете ни модели дисков, ни что они хотя бы одноклассники. Честно не помню, какие диски вы ставите обычно, для нас вы собирали кастомные конфигурации с оговорёнными конкретными моделями дисков под write intensive базы. Но часто если хостер говорит в описании что поставит абстрактное "2 × 960 ГБ SSD NVMe", то на двух одинаковых заказанных одновременно серверах запросто можно увидеть разные диски (а то и на одном сервере две разные модели, привет hetzner'у).

Различие конфигурации должно устраняться или хотя бы подтверждаться тестом, что оно не является значимым фактором для результата тестирования. У вас есть тест, что различие в объёме RAM 192 и 512гб не имеет значения для результата теста? (а про частоту и тайминги вы тоже не писали в статье)
В частности, вы так же не указали, сколько у вас каналов памяти вообще работает. Для того же восьмиканального 6336Y может быть значимым различие, установлено ли 16 модулей по 16гб или 8 по 32гб или максимальным поддерживаемым объёмом одного DIMM (4 по 64? 2 по 128?).

Объём разный. Особенно на не топовых по объёму моделях это очень часто означает разницу производительности. Иногда кратную.
Ну например, самсунговый PM9A3 https://semiconductor.samsung.com/ssd/datacenter-ssd/pm9a3/ :
объёмом 960гб - 70к IOPS random write, а 1920гб - уже 130к IOPS. Почти двукратно по спецификации. Что там в реальности - тема отдельного вдумчивого теста.

ну я понимаю маркетинг, но заявлять что сравниваете производительность ARM и x86 в базах данных, но ставить разные диски участникам? Это же в принципе лишено смысла. В сравнении должен быть минимум различий. Одна и та же физически пара накопителей должна переставляться с сервера на сервер для корректного сравнения возможностей именно CPU, а не дисков.

Аналогично по RAM, впрочем я не вижу у вас scale factor, так что от него значение меньше.

Корректный заголовок "погоняем синтетику на наших тарифах", исключив при этом из теста кастомную конфигурацию.

У listen/notify, конечно, вагон своих особенностей (начиная с того что они принципиально не crash safe), но советовать вместо них, упирая именно на производительность обработки, наиболее топорную самодельную очередь в базе? Очередь в базе - известный антипаттерн, приводит к головной боли.

work mem же... Вот сначала совершенно верно написано "сколько памяти доступно каждой операции запроса", а потом приводится классический неверный совет делить поровну на max_connections. Неверный именно потому, что work_mem - это память на одну операцию. И то без учёта hash_mem_multiplier. Один сложный OLAP запрос может сожрать десятки work_mem. Поэтому выставляется в разумное значение и отслеживаются потребности. pg_stat_statements тот же пишет temp_blk_write_time и temp_blk_read_time. Вполне обычная ситуация, когда для OLTP части work_mem небольшой, десятки мегабайт, а для пользователей со всякими отчётами work_mem выставлен именно на пользователя побольше. Или в целом на отдельной реплике, куда не ходят на OLTP данными.

справедливости ради, вы всё-таки не правы про "не планировавшиеся еще несколькими месяцами ранее", мне письмо счастья пришло ещё 14 декабря (за 4 полных месяца), первые получившие такие письма чуть ли не с ноября начали появляться.
С этой стороны претензий нет, сообщили вполне заранее.

Но ящик должен быть корпоративным?

а других, с точки зрения самого яндекса, нет. Не предложено никакого деления на личные и корпоративные. У меня, говорят, пяток "сотрудников". А пару недель назад пройти опрос предлагали, где ОГРН было сделано обязательным для заполнения полем.
Вопрос, что это просто личный домен одного человека (ну или семьи, как упоминается в статье) - просто проигнорирован и всех назвали бизнесом.

Information

Rating
2,925-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity

Specialization

Database Administrator
Lead
PostgreSQL