Предлагаю ознакомиться с расшифровкой доклада 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_start_backup. И уже потом сделать rsync с мастера на реплику. Вот тогда вы можете более-менее себе гарантировать, что у вас rsync правильно сделает все, что вам нужно. Но не забывайте, что если у вас будет несколько дисков и вы забудете, допустим, про tablespace на HDD, сделаете rsync и запустите, то у вас сначала будет работать. А потом сделаете промоут – и все, реплики нет. Там очень много моментов, где вы можете ошибиться и просто испортить свою реплику. Лучше – надежный pg_basebackup.


Спасибо за доклад! Вы сначала сказали, что следует сначала обновить реплики…


Это касается минорного обновления.