"Деплой кода процедур" Мурат Кабилов (Avito)

19
Деплой кода процедур Мурат Кабилов, Avito PostgreSQL meetup @ Avito 09.04.2016

Transcript of "Деплой кода процедур" Мурат Кабилов (Avito)

Деплой кода процедурМурат Кабилов, Avito

PostgreSQL meetup @ Avito 09.04.2016

Контекст

• много хранимых процедур >500

• большой размер базы ~2 TB, большой TPS

• много разработчиков

• много веток

2

Проблема

• деплоить несколько версий процедур на одной базе

• удобное версионировение кода хранимых процедур

• применение DDL изменений

• массовые update'ы

3

Решение «Zalando»

• под каждую выкатку создавать схему со всеми х/п

• замена search_path

• плюсы: простое решение. Схема дает самодостаточность

• минусы: много изменений для системного каталога

версия отражается в названии схемы

4

Решение

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

• название хранимой процедуры содержит версию

• иметь php-словарь с маппингом хранимая процедура — версия

• приложение «решает» какую версию использовать

версия отражается в названии хранимой процедуры

5

GIT

• [master] • [public.item_save.sql] • [public.get_matrixes.sql]

• [master2] • [public.phone_save.sql] • [public.phone_validate.sql] • [xrpc.clear.sql] • [payments.pushup.sql]

6

GIT

• содержимое public.get_matrixes.sql: CREATE OR REPLACE FUNCTION public.get_matrixes(OUT o_matrix_id integer) RETURNS SETOF integer LANGUAGE sqlAS $function$ select matrix_id as o_matrix_id from my_schema.matrix_probabilities order by matrix_id;$function$

ALTER FUNCTION public.get_matrixes SET work_mem = '100 MB';

• инициализация/дамп, например, через pg_get_functiondef()7

Маппинг. БД

• Таблица stored_procedures: • branch_name — имя ветки • fn_name — имя хранимой процедуры • fn_md5 — хеш от файла хранимой процедуры • ver_id — порядковый номер версии хранимой процедуры

8

Маппинг. Приложение

• Файл-словарь Obj_Sproc_Version.php: <?php// generated by Obj_Dict_Indexed::storeDict() (see Obj_SPVersion::getDict())return [ 'public.get_matrixes@master' => 1, 'public.item_save@master' => 15, 'payments.pushup@master2' => 0, 'xrpc.clear@master2' => 3, ...

9

Деплой

• содержимое public.get_matrixes.sql: CREATE OR REPLACE FUNCTION public.get_matrixes_ver2(OUT o_matrix_id integer) RETURNS SETOF integer LANGUAGE sqlAS $function$ select matrix_id as o_matrix_id from my_schema.matrix_probabilities order by matrix_id desc; $function$

10

Деплой

11

-[ RECORD 1 ]-+--------------------------------- branch | master fn_name | public.get_matrixes fn_md5 | e0b02d8234e3bfe283bccad31c1f88fd ver_id | 1

-[ RECORD 2 ]-+--------------------------------- branch | AVITO-3311-matrix-order-desc fn_name | public.get_matrixes fn_md5 | 1b05d042fd37384e47e4403fa65a8f3a ver_id | 2

Деплой

• Файл-словарь Obj_Sproc_Version.php: <?php// generated by Obj_Dict_Indexed::storeDict() (see Obj_SPVersion::getDict())return [ 'public.get_matrixes@master' => 2, 'public.item_save@master' => 15, 'payments.pushup@master2' => 0, 'xrpc.clear@master2' => 3, ...

12

Плюсы и минусы

• Плюсы:

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

• можно хранить несколько версий х/п в одной базе

• легкий «откат»

• Минусы:

• трудности при использовании внутренних х/п

13

Что дальше?

Решить проблему использования внутренних х/п

Деплой v2

• Две схемы: base, diff

• Два пользователя со след. search_path: User_A: base, User_B: diff, base.

• Приложение использует User_A

16

Деплой v2

• При выкатке, все изменившиеся хранимые процедуры создаются в diff схеме

• После деплоя х/п новая версия приложения начинает использовать User_B

• По окончанию выкладки php кода, переносим х/п из diff в base. Меняем местами search_path у пользоватлей:User_A: diff, base, User_B: base

• Приложение использует User_B

17

18

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

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

• откат через деплой

Итог

Вопросы?