Практика обновления версий PostgreSQL. Андрей Сальников
Предлагаю ознакомиться с расшифровкой доклада 2018 года Андрея Сальникова «Практика обновления версий PostgreSQL»
В большинстве своем, системные администраторы и ДБА бояться как огня делать мажорные обновления версий баз данных (RDBMS), особенно если эта база данных в эксплуатации и имеет достаточно высокую нагрузку. Главной причиной тому некоторый даунтайм базы данных, который всегда подразумевается при планировании таких работ.
На практике, такого рода upgrade занимает довольно длительное время и зачастую администраторам с малым опытом подобных операций приходится откатываться на старую версию баз данных из-за достаточно банальных ошибок, которые можно было бы избежать еще на этапе подготовки.
В Data Egret мы накопили огромный опыт проведения мажорных апгрейдов PostgreSQL в проектах, где нет права на ошибку. Я поделюсь своим опытом и расскажу о следующих шагах процесса: как правильно подготовиться к upgrade-у PostgreSQL? что необходимо сделать на этапе подготовки? как запланировать последовательность действий на сам upgrade? как провести процедуру upgrade-а успешно, без возврата на предыдущую версию бд? как минимизировать или вообще избежать простоя всей системы во время upgrade-а? какие действия необходимо выполнить после успешного upgrade-а PostgreSQL? Я также расскажу про две наиболее популярные процедуры апгрейда PostgreSQL — pg_upgrade и pg_dump/pg_restore, плюсы и минусы каждого из методов и расскажу про все типичные проблемы на всех этапах этой процедуры, и как их избежать.
Доклад будет интересен как новичкам так и тем ДБА которые уже давно работают с PostgreSQL, но хотят побольше узнать о том как правильно планировать и проводить upgrade максимально безболезненно.
Здравствуйте! Я тружусь в компании Data Egret. Мы занимаемся тем, что поддерживаем сервера PostgreSQL и оказываем услуги консалтинга PostgreSQL. И практика показала, что очень мало людей обновляют базу данных. Они запустили проект, устанавливают версию актуальную на тот момент и работают до сих пор.
Доклад будет состоять из трех частей. Первая — вводная, чтобы к общей терминологии прийти. Вторая про минорные обновления. И третья про мажорные будет.
Цель доклада — дать ответ на вопросы.
- Зачем нужно обновляться? Обновления необходимы потому, что Postgres не стоит на месте. Там постоянно делают новые фичи, исправляют какие-то баги. И чтобы не прыгать все время на одних и тех же проблемах, лучше обновляться. И все быстрее будет у вас работать, и меньше проблем будет. Это основная цель обновления.
- Расскажу, какие методики обновления существуют в процессе доклада.
- Затрону темы, где у вас могут быть проблемы по той или иной методике и расскажу, как избежать их.
- Немало важный вопрос, который многих беспокоит: «Это возможно ли обновления без даунтайма и как их провернуть?». Про это поговорим.
- Если у вас нет никакого опыта в обновлении, опираясь на этот доклад вы сможете сами попробовать это сделать. Сможете сначала на кошках потренироваться, а потом уже и production базы данных обновлять.
В общем основная цель в том, чтобы люди старались поддерживать у себя актуальную версию Postgres.
Немного вводной информации о том, как нумеруются версии, чтобы общее понимание было. До 10 версии у нас нумерация бывает из трех цифр. Первые две цифры, разделенные точкой, отвечали за мажорную версию, последняя цифра — это минорная версия.
Начиная с 10-ой версии сообщество решило изменить стиль нумерации. Теперь у нас два числа, разделенные точкой. Первое число — это номер мажорной версии, последнее число — номер минорной версии.
Какие могут быть типы обновлений?
Минорные обновления. Тут важно понимать, что минорные обновления — это обновления в рамках одной мажорной версии. Если вы работаете с версией 9.6 и обновления между этими мелкими пачами, которые приходят, довольно важны, то будут обновления минорные. Это по последней цифре. Они самые легкие.
Для 10-ой версии начинается новый стиль нумерации. Ничего не изменяется, последнее число отвечает за минорную версию.
Мажорные обновления. Тут все достаточно интересно. В мажорных обновлениях мы прыгаем между версиями и стремимся за новыми фичами и возможностями баз данных, и всякими плюшками.
Тут уже минорные версии базы уже не играют роли. При мажорном обновлении мы будем стараться обновляться на самую последнюю доступную версию релиза.
Актуальные версии на сегодняшний день — это те, куда приехали патчи минорных обновлений. Их 6. Но одна помечена красным. И помечена по той причине, потому что эту версию сообщество уже перестало поддерживать. Т. е. они попатчили в 9.2. Это был последний патч, больше не будет, про 9.2 можно забыть. Если вы работаете на 9.2, то вам самое время обновляться.
Любая процедура обновления будет состоять из двух вещей: мы готовимся и делаем обновление.
Есть общие рекомендации. Перед любым обновлением, не зависимо от того минорная или мажорная эта версия, необходимо будет проделать перед обновлением на production следующее:
- Очень важно прочитать полностью release notes. Что под этим я подразумеваю? Обычно, если люди и читают release notes, то читают release notes по главной мажорной версии, потому что там много всего написано. Написано про вкусняшки, которые там разработчики сделали. А минорные как-то упускают. А минорные обновления несут серьезные багфиксы, потому что все мы люди и разработчики тоже люди и когда выкатывается новый релиз, он еще достаточно сырой и там приходят очень много патчей. К примеру, мы до сих пор не очень стремимся устанавливать 10-ку клиентам, потому что ожидаем второй патч-сет. Только после этого, скорее всего, займемся вплотную этим.
- Почему вам нужно будет обновиться на тестовом окружении? Причина простая. Нужно проверить, как ваша система будет работать с новой версией базы данных. Если вы не читали release notes, то для вас могут будут сюрпризы. Например, приложение не будет работать с какой-нибудь специфической фичей. В основном, Postgres обратно совместимый и проблемы возникают редко, но бывают, что возникают. Поэтому погонять свое приложение на тестовом окружении всегда полезно, не только с точки зрения обновления Postgres, но и разработки.
- Если вы столкнетесь с какими-то проблемами, то вам нужно будет подойти к своим разработчикам, которые писали приложение и рассказать, что необходимо поменять и как это необходимо поменять, иначе у вас потом сюрпризы в production полезут.
- И вещь, которая нужна всегда и везде и о чем мы не перестаем напоминать — это то, что бэкапирование нужно везде и всегда. И бэкапирование настоящее — это то, когда вы с бэкапа поднялись, подключили свое приложение к базе и у вас все заработало, и нет никаких проблем. Все данные консистентные и все хорошо.
Советы общие, но частенько ими, к сожалению, пренебрегают.
Теперь перейдем к самим обновлениям. И начнем от легкого к более тяжелому по количеству действий и пониманию.
Минорное обновление хорошо тем, что несет исправления в коде самой базы данных. У нас не происходят никаких изменений со структуры данных, с внутренним представлением системного каталога Postgres. Там багфиксы самого движка Postgres.
Как это происходит:
- Установите пакеты с новой версией PostgreSQL. Но тут важно понимать, что если вы пользуетесь какими-то стандартными репозиториями, то у вас, скорее всего, Postgres запущен как сервис. И установка пакетов перезапустит этот сервис. И вы себе установите небольшую аварию с установкой базы данных и своего приложения. Поэтому на этом акцентуируйте внимание и устанавливайте пакет так, чтобы не рестартовали. В Ubuntu, например, есть стандартный конфигурационный файл для каждого кластера, который создается. Называется он start.conf. И вы там можете поправить режим перезапуска сервисом конкретного кластера. Можете запретить сервису его рестартовать автоматически.
- Необходимо установить связанные с PostgreSQL другие пакеты. Если мы обновим только серверный пакет, то автоматически у вас по связям не подтянутся ни клиентская часть, не common-пакет и пакет расширения тоже может не подтянуться. Будьте внимательны тут.
- Следующий — checkpoint. Зачем нам нужен checkpoint? Когда у нас работает база данных, то все изменения происходят у нас в памяти. И когда мы начнем останавливать базу данных для перезапуска, то база данных начнет активно все, что наработала в памяти, скидывать на диск. И это нам устроит небольшой коллапс, потому что, если у нас очень огромная оперативная память, допустим, 250 GB, то моментально скинуть их на диск мы не сможем. Поэтому нужно предварительно об этом позаботиться и выполнить checkpoint, который произведет сброс всех данных из памяти на диск и облегчит нам дальнейшую жизнь при рестарте Postgres.
- Как избежать даунтайма? Если вы используете pgbouncer, то он в данном случае поможет приложениям прозрачно оставить соединение с базой данной, потому что он является прослойкой между базой данных и приложением. Приложение входит в pgbouncer, а pgbouncer входит в базу данных. И pgbouncer«у мы можем сказать — поставь на паузу приложение, а сами в это время по-тихому перезапустить базу данных с новой версией бинарника. Для приложения это будет как большой latency при ответе запросов. Т. е. они подвиснут на время рестарта, потом мы снимем с паузы pgbouncer, и приложение начнет работать снова. Если вы предварительно сделаете checkpoint, паузу в pgbouncer, то рестарт у вас займет в зависимости от активности в базе данных от секунды до полминуты.
- И перезапускаем базу данных, чтобы она заработала с новыми бинарниками. Никаких изменений в файловых данных у нас в это время не происходит. Мы просто запускаем новые бинарники, которые работают с теми же данными.
- Некоторые багфиксы, обновления могут повлиять на extensions, если вы используете какие-то специфические extensions. И поэтому рекомендую — не полениться пройтись по всем базам и обновить все extensions в каждой базе данных. Это очень полезно. Особенно это полезно будет при мажорных обновлениях. Там это совсем яркая проблема. На минорных я пока не сталкивался. Но я их обновляю всегда.
- И также минорные обновления (возвращаюсь к тому, что очень важно читать release notes) иногда требуют дополнительные процедуры из release notes. Каждый раз от каждого минора к следующему минору — это могут быть какие-то специфические вещи. Допустим, если вы обновляетесь с 9.6.1 на 9.6.6, которая сейчас актуальна, то вам нужно прочитать release notes для 9.6.2 — 9.6.6. И если вы сталкиваетесь с какими-то проблемами, то вычленить оттуда то, что вам нужно будет сделать после того, как вы перезапустите базу с новыми бинарниками.
- Если вы работаете со standby серверами, с потоковой репликацией, то реплики лучше и правильней обновлять до обновления Мастера сервера. Недавно у нас возникла ситуация, когда у клиента был Мастер 14-ой минорной версии, а реплика была 2.3 и у нас встала репликация. Он миграцию схем данных запустил. Перестроились синтаксисы и у репликации был баг, она встала и перестала работать. Крутилась в бесконечном цикле.
Это к важности того, что нужно читать release notes.
Вот эта конкретная вырезка из официального Postgres.org. Релиз для версии 9.6.2. И тут черным по белому написано, что в этом релизе пофиксили создание конкурентных индексов всех.
Суть бага в чем была? Если ранее вы создавали конкурентный индекс по полю, по которому никогда до этого не было индекса и не участвовало оно ни в каком другом индексе, то у вас мог оказаться битый индекс и вы об этом бы не узнали. Потому что в базе данных он у вас выглядел бы валидным, а по факту в индексе были бы пропущены значения или ссылки были бы не на те строки в таблице. Что в итоге приводит к неожиданным результатам выполнения запросов.
И вот таких интересных штук в каждой минорной версии много. Просто так минорные версии сообщество не выпускает. Будьте внимательны. Читайте, пожалуйста, release notes. Это очень важно.
И вот иллюстрация о том, что пакеты по зависимостям не тянутся. В данном случае я обновлял серверную версию. Вы, как видите, что сервер у меня 9.6.5. А клиент по зависимостям у меня не подтянулся 9.6.1. Это тоже не очень хорошо, потому что не гарантируется обратная совместимость. И могут быть какие-то проблемы с клиентом. На минорной версии это мало вероятно, с мажорной — большая вероятность может быть. Поэтому обновили серверную часть — обновляйте другие пакеты.
И пример того, как нужно пройти по расширениям. Т. е. по каждой базе bash-скрипт напишите, который по каждой базе идет и тянет имя расширения. И просто нагенерируете себе alter extension, update и для душевного спокойствия запустите.
Какие итоги можно сделать?
- Делается просто. Мы просто устанавливаем новый пакет. Делаем несложные действия, чтобы произвести рестарт базы данных достаточно безопасный и прозрачный для приложения, чтобы его никак не задействовать и никак не повлиять на него.
- Каждое минорное обновление несет существенное исправление ошибок. Да, у вас может не возникнуть эта ситуация сейчас, но в следующем миноре может возникнуть такая проблема, поэтому читайте release notes.
- Как дополнительный эффект багфиксы несут улучшение производительности. Допустим, в параллельном сканировании есть какой-то баг, который пару лишних цифр добавляет. Ребята выкатили минорное обновление. Убрали лишние циклы. И у вас параллельное сканирование идет быстрее.
- И минимальный простой системы, т. е. у вас база не доступна ровно в рестарт. Вы ее остановили, если сделали правильно с checkpoint, то у вас рестарт базы от миллисекунды до 30 секунд максимум занимает.
Самая большая и интересная часть доклада — это мажорные обновления.
Есть несколько методик мажорных обновлений. Кому какая подходит, тот ту и выбирает. Моя цель рассказать о каждой и них.
- Pg_dump и restore — это самая старая и добрая методика. Мы ею до сих пор иногда пользуемся, потому что надежнее нее ничего нет. Но у нее есть куча-куча недостатков для современно мира.
- Pg_upgrade — это наша любимая утилита, которой мы пользуемся, наверное, в 95% случаев, когда проводим мажорные обновления базы данных. А проводим мы их еженедельно точно.
- И также основанные на репликациях обновления.
И эти обновления тут стоят в порядке усложнения.
Как с помощью pg_dump будет выглядеть для вас процедура обновления?
- Устанавливаем пакет с новой мажорной версией. Тут нам не стоит переживать, потому что это разные пакеты. Один пакет 9.5, к примеру, другой пакет 10. В Ubuntu нужно быть внимательным, в RedHat ветке можно не париться — не рестартанет Postgres. Но помним, чтобы случайно не перезапустить текущую рабочую базу данных.
- Создаем пустой кластер в той же locale, в которой существует текущая работающая база данных.
- Пробегаемся по конфигам Postgres, потому что, если вы им пользуетесь, то вы, скорее всего, их крутили и дефолтные параметры некоторые вам не нужны.
- И дальше начинается та вещь, которая не удовлетворяет большинство людей в проведении апгрейда базы данных при pg_dumop. Нам необходимо остановить модификацию данных в PostgreSQL. Зачем нам это нужно сделать? Если мы pg_dump пользуемся для снятия дампа, то мы снимаем снапшот на момент, когда он стартанул, но база может продолжать писать в этот момент изменения в себя. Нам изменения не нужны, потому что мы хотим перенести весь объем данных из старой базы в новую, чтобы они были актуальные и самые свежие. И это можно сделать только одним способом. Остановив запись в PostgreSQL, т. е. остановив приложение, закрыв порт. Там путей много разных, выбирайте удобный для себя.
- С остановки модификации данных начинается даунтайм. И это главный недостаток pg_dump, потому что после этого мы создаем дамп базы данных. И тут время полностью прямо пропорционально размеру вашей базы. Чем больше база данных, тем дольше вы будете ждать создание дампа.
- А потом еще и восстановление дампа в новую версию. Но зато дамп вам гарантированно восстановит вашу базу данных в новую версию с некоторыми оговорками.
- И после того, как мы восстановили дамп на новой версии, запускаем приложение так, чтобы оно писало уже в новую версию PostgreSQL.
Сложная и нудная процедура, но есть случаи, когда без нее никак не обойтись, к сожалению.
Некоторые особенности pg_dump:
- Некоторые сложности с обновлением нагруженных баз данных. Сложность одна — даунтайм. Большой и неприемлемый в современном мире.
- Мы останавливаем приложение. Это тоже последствие даунтайма.
- Требует дополнительное дисковое пространство. Тут есть варианты: в два раза, в три раза, можно и больше. Все зависит от того, как вы снимаете дамп.
- Если вы снимаете дамп промежуточно на диск, то есть у утилитки хорошая опция, которая позволяет вам при снятии дампа сразу его архивировать и складывать упакованным на диск. Это позволит вам сохранить место.
- Также вы можете параллельно это снимать. Если вам дисковая система позволяет, то вы можете распараллелить снятие дампа. И это вам позволит быстрее обрабатывать данные. Но это касается SSD-систем, где SSD-диски используются хорошие. Но если вы хотите переливать дамп со старой базы в новую без промежуточного хранения на диске, то параллельно это не получится, к сожалению. И это тоже недостаток достаточно большой дампа.
- И эта вещь очень важная. Прежде чем делать апгрейд, мы всегда снимаем схему базы данных со старых версий и накатываем в новую версию. И эта процедура нам позволяет поймать большинство граблей, которые могут встретиться. Например, несовместимые версии расширений, пропали типы. И снятие только схемы восстановления, только схемы данных позволяет поймать все эти грабли до того, как вы реально запустите дамп с даунтаймом. Это позволит избежать многие проблемы.
Теперь переходим к нашей любимой утилите, к pg_upgrade.
- Pg_upgrade намного сложнее с точки зрения подготовки проведения апгрейда. Но если вы с ним будете близки, т. е. потренируетесь, то вы его полюбите. Предварительная подготовка сложная.
- При определенных обстоятельствах вы можете запороть себе базу данных. Как это происходит я вам расскажу и, надеюсь, что вы так не сделаете.
- Это самый быстрый способ обновления PostgreSQL. И самый дешевый по ресурсам и по ресурсам человеко-часов, а это самый ценный ресурс в нашей жизни.
- Могут быть проблемы после обновления. О них я расскажу чуть попозже.
Небольшой ликбез, как работает pg_upgrade. На входе мы должны иметь две базы данных: старую, которая у нас с данными и новый кластер пустой, который мы создали.
Соответственно, когда мы запускаем pg_upgrade, и он начинает делать свое светлое дело, то в первую очередь он чистит информацию в новом кластере о счетчиках транзакции, потому что нам нужно перенести счетчик транзакции из старой базы в новую. И когда мы стартанем, начнем ровно с того места, на котором мы закончили в старой версии базы данных. Тут происходит перенос этого счетчика транзакции.
И последняя самая массивная, но самая веселая вещь — pg_upgrade делает dump и restore схемы, он запускает pg_dump, restore с некоторыми флажками для того, чтобы восстановить новой базе всю схему данных, которая была в старой базе данных, но не переносит при этом данные. Это именно схема.
А перенос данных может быть осуществлен двумя вещами. Мы можем скопировать файлы с данными, а можем сделать хардлинк на существующие данные, потому что блок данных у нас не меняется с версией 8.4. В Postgres и мы можем позволить себе такой финт ушами.
И когда мы делаем хардлинк, то у вас в этот момент смотрят две версии базы данных (допустим, 9.0 и 10) на одни и те же дата-файлы. И если вы одновременно обе их запустите, то ваша база данных превратиться в тыкву, с которой вы потом ничего не сделаете. Поэтому будьте очень осторожны с линком. Но мы делаем через линк всегда, у нас руки не дрожат.
Тут именно такая процедура подготовки, которую мы всегда делаем перед реальным апгрейдом на production. Т. е. прежде чем устроить даунтайм и коллапс, мы сначала проверяем — действительно ли мы это можем сделать.
- Ставим новые пакеты новой версии PostgreSQL.
- Создаем новую базу в правильной locace. Это общие шаги.
- Делаем pg_upgrade. Запускаем с ключом «check». Check делает почти все, что может апгрейд сделать в реальности. И при этом, если у вас есть какие-то несовместимости с типами данных, со схемой и это все вылезет, то он ругнется, отвалится, но при этом вы не попортили старую базу и не сделала никаких изменений в пустом кластере. И вы можете сразу прекратить процедуру апгрейда, запланированный даунтайм и общий кипеш. И вернуться к тесту и посмотреть, что у вас там не так и исправить это.
- Pg_dumpall — schema-only. К сожалению апгрейд с check не все показывает. И мы себя дополнительно проверяем через pg_dumpall — schema-only, и накатываем новую базу данных. Недостаток этой процедуры в том, что потом придется пересоздать кластер заново пустой. Но она того стоит, потому что бывали ситуации, когда check не поймал у нас проблему апгрейда, а dump поймал.
- Заодно с некоторыми extensions есть особые ситуации. Особый яркий пример — это PostGIS, потому что PostGIS обновляется до обновления Postgres. Этот extension всегда нужно обновлять до обновления Postgres, потом обновлять сам Postgres. Нужно почитать changelog и выяснить — можете ли вы вот так просто, пользуясь pg_upgrade обновить, потому что на старых версия этого сделать было нельзя. Там требовалось через dump restore делать.
Сама процедура обновления, после того, как вы подготовились, довольно простая.
Создаем базу в новой locale, если мы пользовались pg_dumpall only, restore.
Останавливаем старую базу данных. При этом не забываем о том, что pgbouncer нам поможет подвесить соединение к базе данных, т. е. приложение не потеряет соединение, а просто подвиснут.
Не забываем про checkpoints, которые нам помогают очистить память и скинуть ее на диск, чтобы побыстрее остановить базу данных.
И следующим шагом запускаем обновление pg_upgrade. Сама процедура переноса счетчика транзакции, схемы данных и линковки довольно быстрая. Время обновления зависит от размера вашей базы данных именно в количестве объектов в базе данных. Может занять от минуты до 45 минут. Был у меня один раз критичный момент, когда обновление шло 45 минут, но это отдельная история. Чаще всего обновление занимает от минуты до 15 минут, независимо от размера базы данных. Это зависит от количества объектов в базе данных созданных.
Если мы копируем файл, то будет зависимость от размеров базы данных. Мы делаем через hard links. И создание линков занимает секунды в нормальной ситуации.
И запускаем новую версию PostgreSQL. Но мы еще не разрешаем приложению туда ходить. Почему мы не разрешаем приложению ходить в новую версию PostgreSQL? Потому что там нет статистики. К сожалению, pg_upgrade теряет статистику при обновлении.
И нам нужно собрать эту статистику.
И после этого мы разрешаем соединения с базой данных. Даунтайм у нас в зависимости от ситуации составляет от одной до 10 минут. И еще зависит от опытности человека, который проводит этот даунтайм.
По сбору статистики есть следующие замечания:
Стандартно pg_upgrade генерирует скрипт по сбору статистики. Суть его в том, что запускается вакуум по всем базам данных в трех стадиях: по одной цели, по 10 целям и полный сбор статистики.
Если у вас база небольшая или в ней немного объектов, то можно запустить сразу полноценный сбор статистики, игнорировав автосгенерированный скрипт.
Начиная с версии 9.5 можно немного подредактировать этот скрипт. В зависимости от того, сколько у вас ядер и насколько у вас позволяют диски и можно распараллелить сбор в статистики.
Мы обычно используем стандартный скрипт. И делаем следующим образом. Без статистики у нас планировщик сойдет с ума, он не будет знать, как правильно ему строить планы. Поэтому мы ждем, пока у нас vacuumdb соберет статистику по 1, 10 целям. И когда он уже приступает к сбору полноценной статистики, мы разрешаем соединение к БД приложению. Уже более-менее адекватной становится работа с базой данных. Планировщик более-менее адекватен. Хотя выверты могут быть, но это не так страшно, нежели ждать полной сборки статистики.
Но тут есть один фактор. Если приложение активно начинает менять записи в базе данных, то у вас возникнет блокировка. У вас придет автовакуум в какой-то момент. И возникнет блокировка между вакуум, который мы запустили после апгрейда, и автовакуумом. В это время нужно посидеть и последить за блокировками, прибивая автовакуум, чтобы он не мешал полноценному сбору статистики после апгрейда.
Кратко о процедуре обновления на слайде.
- Pg_upgrade не обновляет extensions. Это такой же недостаток, как отсутствие статистики.
- Не забудьте почитать release notes для расширений.
- После того, как вы обновитесь, вам придется пройтись по всем extensions и обновить их вручную сказать — alter extension EXTENSION_NAME update. Это обязательно. Если вы используете pg_stat_statements, то в какой-то версии они изменили количество столбцов. Обновились вы через pg_upgrade, вы не увидите новые столбцы со статистикой от pg_stat_statements. То же самое касается других расширений. Обязательно по всем пройтись надо.
Очень часто задают вопрос — как обновлять реплики? Делается это просто:
- Сначала обновляем мастер-сервер по какой-нибудь процедуре.
- Далее мы смотрим, что у нас все хорошо, приложение работает с мастером, мы нигде не накосячили, все счастливы, все работает. И тогда реплика нам не нужна. Потому что, если мы накосячили, нам будет куда откатиться и сделать промоут старой реплики старой версии.
- Как мы это проверяем? Мы просто смотрим лог Postgres. И смотрим наличие ошибок и внештатных ситуаций. Разное время на это уходит. Бывает, сутки смотрим, бывает, 10 минут смотрим.
- После этого мы на серверах с репликами устанавливаем новую версию PostgreSQL.
- И pg_basebackup копируем базу данных с обновленного мастера на реплику. Старая версия реплики нам не нужна.
- Запускаем реплику на новой версии PostgreSQL.
- И если вы неопытной, то мы не рекомендуем вам использовать rsync, потому что это сложный и трудоемкий процесс. Можно обновить так, но, скорее всего, вы допустите ошибку и у вас реплика превратится в бесполезный набор файлов. Поэтому до rsync дойдите только тогда, когда наберетесь опыта.
Мы не очень это любим. Причин тут несколько:
- Во-первых, потоковая репликация не работает между разными версиями PostgreSQL.
- Работают только логические виды репликаций. Их несколько видов.
С версией 9.4 появилась встроенная логическая репликация. С каждой версией она развивается. И я думаю, что с версии 10 на версию 11 можно уже с ее помощью мигрировать довольно легко.
Есть также сторонние репликации, которые появились ранее. Это Slony-l, Londiste, Bucardo и т. д. Их можно использовать.
Как выглядит процедура обновления с помощью логических репликаций?
- Мы настраиваем новую версию PostgreSQL.
- Каким-то образом переносим основной объем данных из старой версии Postgres в новую версию Postgres.
- И настраиваем репликацию, чтобы изменения, которые у нас идут реплицировались в новую версию. Для каждой логической репликации будет свой путь.
- Потом убеждаемся, что мастер и реплика в достаточно консистентном состоянии. Там есть несколько путей. Или сразу переключаем приложение, чтобы оно работало с репликой в новой версии Postgres. Или поочередно переключаем, если у вас микросервисная структура, т. е. по одному приложению начинаем переводить. Это зависит от того, как у вас организовано.
- И после этого тушим старую версию Postgres, убедившись, что туда ничего не пишется.
- И делаем для себя промоут логической реплики новой версии Postgres, и работаем на ней. Даунтайма, в принципе, нет при переключении приложения. В любом случае нам что-то всегда останавливаться.
Какие проблемы будут при этом присутствовать?
- Вы замучаетесь настраивать логическую репликацию для сложных схем БД, когда у вас десятки тысяч таблиц. Есть какие-то автоматические инструменты.
- Как правило, логические репликации переносят данные. Это на текущий момент ситуация. Т. е. данные, которые хранятся в таблице.
- Но у нас есть еще sequences, которые нам нужно будет потом синхронизировать как-то.
- У нас может прийти DDL, который нам подпортит все. Потому что DDL логические репликации, как правило, не обрабатывают. И если вдруг девелопер решил задеплоить изменения в схемах данных, станет плохо.
- Нужны будут дополнительные объемы дискового пространства, потому что это у нас две работающие базы данных, как минимум.
Тут небольшая сводная таблица, в которой приведены плюсы и минусы того или иного вида мажорного обновления. И довольно привлекательно выглядит pg_upgrade с линковкой файлов и логическая репликация, если вы действительно решите ее настраивать.
Почему мы используем апгрейд? Потому что, если у вас база 3 TB, то не все могут позволить себе 2 SSD RAID по 3 TB. Это достаточно дорогое удовольствие. А тут мы обновляемся ровно на те же файлы.
В случае с логической репликацией нам нужно больше дискового места. Это не всегда возможно.
Я посчитал, что Амазон дает гарантию, что у вас сервер работает 99 и сколько-то 9-ок после запятой. Это всегда больше 15 минут. Тут у вас даунтайм будет меньше 15 минут в общем случае. Я думаю. Что это позволительный даунтайм даже для очень онлайн-онлайн системы.
Тут приведены ссылки на полезную информацию, которую вы можете прочитать от разработчиков pg_upgrade. Также почитать об особенности сбора статистики. Там дополнительная и более детальная информация по этой теме.
На этом у меня все.
Вопросы
Добрый день! Когда мы ставим pgbouncer и потом включаем после рестарта, то если у нас идет большая нагрузка, то, соответственно, нам нужно еще дождаться, когда прогреются кэши. Как эта проблема у вас решается?
Нам в большинстве случаев кэши не приходится прогревать, потому что у нас большинство клиентов на SSD сидят хороших. И там разница чтения между операционной памятью и SSD не сильно большая, т. е. незаметно это время прогрева кэшей. Оно не сильно влияет на производительность систем. Но, конечно, просаживается, это да, надо подождать пока прогреются. И бывает, что если специально не прогревать, то может длиться часами прогрев кэшей. Это зависит от того, насколько активно идет общение с Postgres. Но специально мы обычно не прогреваем, только по просьбе.
К расширениям типа pg_worm и pg_hibernate, как относитесь для прогрева?
Я говорю, что мы в большинстве случаев не прогреваем, потому что оборудование у клиентов позволяет.
Спасибо за доклад! Можно ли реплики не перескачивать после обновлением pg_upgrade?
В принципе, можно. И те же ребята из Яндекса могут рассказать, как это делать. И смогут рассказать более подробно о граблях, на которых они попрыгали. Мы стараемся этого избегать, потому что довольно неизвестны последствия, если где-то пропустишь шаг, реплика может быть нерабочей. И когда нужно будет делать промоут на реплику, мы можем получить не базу, а просто набор файликов. И мы можем не знать об этом совсем, пока не сделаем промоут.
Там через rsync как-то?
А что rsync? Rsync можно с разными ключами запустить. Вы запустите, и он у вас не обновит файл, потому что даты, допустим, совпадают. Как это должно быть? Вы должны параллельно запустить сразу pg_upgrate мастер и реплики. Поднять мастер, собрать статистику. Потом на мастере сказать — pg