Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Изменение схемы таблиц без долгих блокировок в PostgreSQL

Изменение схемы таблиц без долгих блокировок в PostgreSQL

Владимир Колясинский (Яндекс) @ MoscowPython Meetup 60

"Во время многих операций по изменению схемы базы данных сервис не может корректно работать на запись. В докладе я расскажу о том, какие операции в PostgreSql требуют длительных блокировок и как мы в Формах Яндекс.Коннекта обеспечиваем почти стопроцентную доступность сервиса на запись во время выполнения таких операций. Также мы поговорим о Django-библиотеке, призванной автоматизировать некоторые из описанных процессов".

Видео: http://www.moscowpython.ru/meetup/60/change-postresql-table-schema/

Moscow Python Meetup

September 21, 2018
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. 4

  2. Операции требующие длительной блокировки Как избежать блокировок по время этих

    операций Операции не требующие длительной блокировки Библиотека zero_downtime_migrations Содержание 5
  3. 7 ALTER TABLE table ALTER COLUMN column TYPE VARCHAR(32) ALTER

    TABLE table ADD COLUMN column boolean DEFAULT True NOT NULL VACUUM FULL table ALTER TABLE table ADD UNIQUE column ALTER TABLE table ADD CONSTRAINT CREATE INDEX Операции требующие долгой блокировки
  4. 〉нельзя запускать в транзакции 〉занимает больше времени 〉потенциально может завершиться

    неудачей 〉не блокирует таблицу на изменения CREATE INDEX CONCURRENTLY 9 Создание индекса
  5. Добавление новой not null колонки с default 10 ALTER TABLE

    data ADD COLUMN some_bool INTEGER DEFAULT 1 NOT NULL; UPDATE data SET some_bool = 1 where id in (select id from data where some_bool is null limit 5000); ALTER TABLE public.comments ALTER COLUMN source_type SET NOT NULL; BEGIN; ALTER TABLE data ADD COLUMN some_bool INTEGER; ALTER TABLE data ALTER COLUMN some_bool SET DEFAULT 1; COMMIT; =
  6. Изменение типа колонки 11 ALTER TABLE table ALTER COLUMN column

    TYPE type USING (…); = ALTER TABLE table ADD COLUMN column_new type; сделать триггер на insert/update перенести данные порциями BEGIN; DELETE TRIGGER trigger_name; ALTER TABLE table DROP COLUMN column; ALTER TABLE table RENAME column_new TO column; COMMIT;
  7. ALTER TABLE large_table ADD CONSTRAINT token UNIQUE USING INDEX token_is_unique;

    12 Добавление уникальной колонки ALTER TABLE table ADD COLUMN column text UNIQUE; CREATE UNIQUE INDEX CONCURRENTLY token_is_unique ON large_table(token); =
  8. Добавление constraint 13 ALTER TABLE large_table ADD CONSTRAINT con1 CHECK

    (column> 100) ALTER TABLE large_table VALIDATE CONSTRAINT con1; ALTER TABLE large_table ADD CONSTRAINT con1 CHECK (column> 100) NOT VALID; =
  9. ALTER TABLE ADD COLUMN 15 ALTER TABLE SET DEFAULT ALTER

    TABLE SET NOT NULL ALTER TABLE RENAME column TO new_column Изменение длины колонки Операции не требующие долгой блокировки ALTER TABLE DROP COLUMN
  10. 16 ALTER TABLE table_name ADD CONSTRAINT constraint_name CHECK (column IS

    NOT NULL) NOT VALID; ALTER TABLE table_name VALIDATE CONSTRAINT constraint_name; 〉существует отдельно от колонки (на уровне таблицы) 〉0.5-1% влияние на производительность 〉документация советует явно указывать NOT NULL у колонки ALTER TABLE table_name ALTER COLUMN column SET NOT NULL Установка колонки not nullable =
  11. 〉быстрая операция по умолчанию 〉колонка помечается устаревшей в pg_attribute 〉удаление

    с файловой системы происходит только после VACUUM DROP COLUMN 17 Удаление колонки
  12. ZDM Текущие возможности 19 https://github.com/Smosker/zero-downtime-migrations 〉добавление колонки с default значением

    (nullable or not nullable) 〉добавление индекса 〉возможность перезапуска при возникновении ошибок
  13. Подключение 20 # settings.py DATABASES = { 'default': { 'ENGINE':

    'zero_downtime_migrations.backend', ... } } 〉Возможно использование в качестве Mixin в ваших собственных DataBaseWrapper/ SchemaEditor
  14. Пример работы 21 ALTER TABLE "test" ADD COLUMN "field" boolean

    DEFAULT True NOT NULL; ALTER TABLE "test" ALTER COLUMN "field" DROP DEFAULT; Стандартный SchemaEditor BEGIN; ALTER TABLE "test" ADD COLUMN "field" boolean NULL; ALTER TABLE "test" ALTER COLUMN "field" SET DEFAULT true; COMMIT; SchemaEditor из библиотеки
  15. 22 WITH cte AS ( SELECT id as pk FROM

    "test" WHERE "field" is null LIMIT 10000) UPDATE "test" table_ SET "field" = true FROM cte WHERE table_.id = cte.pk ALTER TABLE "test" ALTER COLUMN "field" SET NOT NULL; ALTER TABLE "test" ALTER COLUMN "field" DROP DEFAULT;
  16. 23 Выводы перед запуском django миграций следует запускать sqlmigrate достигаем

    высокой доступности на запись используя библиотеку библиотека развивается - принимаем пул реквесты с ростом базы миграции могут замедляться в Яндекс.Коннект тысячи RPS, недопустим простой на запись запускаем все новые сервисы и нагрузка только растет