Как стать автором
Обновить

«Про, да не кластер» или как мы СУБД импортозамещали

Время на прочтение7 мин
Количество просмотров7K
image

(ц) Яндекс.Картинки

Все персонажи вымышлены, торговые марки принадлежат их владельцам, любые совпадения случайны и вообще, это моё «субъективное оценочное суждение, пожалуйста не ломайте дверь...».

У нас есть немалый опыт перевода информационных систем с логикой в БД из одной СУБД в другую. В разрезе постановления правительства №1236 от 16.11.2016, часто это перевод с Oracle на Postgresql. Как организовать процесс максимально эффективно и безболезненно — мы можем рассказать отдельно, сегодня мы расскажем об особенностях использования кластера и с какими проблемами можно столкнуться при построении высоконагруженных распределённых систем со сложной логикой в процедурах и функциях.

Спойлер – да кэп, RAC и pg multimaster это ну очень разные решения.

Допустим, вы перенесли уже всю логику с pl\sql на pg\sql. А ваши регрессионные тесты вполне себе ОК, теперь вы конечно думаете о масштабировании, т.к. нагрузочные тесты не очень вас радуют, тем более на том железе, которое было заложено в проект изначально, под ту самую другую СУБД. Допустим, вы нашли решение от отечественного вендора «Postgres Professional» с опцией под названием «multimaster», которая доступна только в «максимальной» версии «Postgres Pro Enterprise» и по описанию – это очень похоже на нужное вам, и при первом поверхностном изучении придёт в голову мысль: «О! Вместо RAC самое то! Да ещё и с техсопроводом на Родине!».

Но не спешите радоваться, и дальше мы опишем почему эти нюансы надо знать, т.к. их сложно предусмотреть, даже хорошо почитав документацию по продукту. Оцените, будете ли вы готовы частенько обновлять версии СУБД прямо на промышленной площадке, т.к. некоторые дефекты не совместимы с промышленной эксплуатацией и их сложно выявить на тестировании.
Начните с внимательного прочтения раздела «multimaster» — «ограничение» на сайте производителя.

Первое, с чем можно столкнуться, это особенности работы транзакций, в т.н. «двух фазном» режиме, и иногда, кроме как переписыванием всей логики вашей процедуры, это никак не исправить. Вот простой пример:

create table test1 (id integer, id1 integer);
insert into test1 values (1, 1),(1, 2);
 
ALTER TABLE test1 ADD CONSTRAINT test1_uk UNIQUE (id,id1) DEFERRABLE INITIALLY DEFERRED;
 
update test1
           set id1 =
               case id1
                 when 1
                 then 2
                 else id1 - sign(2 - 1)
               end
         where id1 between 1 and 2;

Возникает ошибка:

ОШИБКА:  [MTM] Transaction MTM-1-2435-10-605783555137701 (10654) is aborted on node 3. Check its log to see error details.

Дальше можно долго бороться с dead lock в версиях 10.5, 10.6 и единственное известное спасение, которое убивает всю суть кластера – это убирать из кластера «проблемные» таблицы, т.е. делать make_table_local, но это хотя бы позволит работать, а не поставит «колом» всё из-за зависших ожиданий фиксации транзакций. Ну или ставить обновление до 11.2 версии, которое должно помочь, а может и нет, не забудьте проверить.

В некоторых версиях вы сможете получить ещё более загадочную блокировку:

username= mtm и backend_type = background worker

И в этой ситуации вам поможет только обновление версии СУБД до 11.2 и выше, а может и не поможет.

Некоторые операции с индексами могут приводить к ошибкам, где явно указывается, что проблема именно в Bi-Directional Replication, в логах MTM вы прямо увидите BDR. Неужели 2ndQuadrant? Да не… мы же купили multimaster, это просто совпадение, это название технологии.

[MTM] bdr doesn't support index rechecks
[MTM] 12124: REMOTE begin abort transaction 4083
[MTM] 12124: send ABORT notification for transaction  (5467) local xid=4083 to coordinator 3
[MTM] Receive ABORT_PREPARED logical message for transaction MTM-3-25030-83-605694076627780 from node 3
[MTM] Abort prepared transaction MTM-3-25030-83-605694076627780 status InProgress from node 3 originId=3
[MTM] MtmLogAbortLogicalMessage node=3 transaction=MTM-3-25030-83-605694076627780 lsn=9fff448 

Если вы используете временные таблицы, несмотря на заверения: «Расширение multimaster осуществляет репликацию данных полностью автоматическим образом. Вы можете одновременно выполнять пишущие транзакции и работать с временными таблицами на любом узле кластера».

Тогда по факту вы получите, что не работает репликация по всем таблицам, используемым в процедуре, если в коде присутствует создание временной таблицы, и даже использование multimaster.remote_functions не поможет, придётся обновляться или переписывать свою логику в процедуре. Если вам надо использовать одновременно два расширения multimaster и pg_pathman в рамках «Postgres Pro Enterprise» v 10.5, то проверьте, что при вот таком простеньком примере:

CREATE TABLE measurement (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

CREATE TABLE measurement_y2019m06 PARTITION OF measurement FOR VALUES FROM ('2019-06-01') TO ('2019-07-01');
insert into measurement values (1, to_date('27.06.2019', 'dd.mm.yyyy'), 1, 1);
insert into measurement values (2, to_date('28.06.2019', 'dd.mm.yyyy'), 1, 1);
insert into measurement values (3, to_date('29.06.2019', 'dd.mm.yyyy'), 1, 1);
insert into measurement values (4, to_date('30.06.2019', 'dd.mm.yyyy'), 1, 1);

В логах на узлах СУБД начинают сыпаться такие ошибки:

…
 PATHMAN_CONFIG doesn't contain relation 23245
> find_in_dynamic_libpath: trying "/opt/…/ent-10/lib/pg_pathman"
> find_in_dynamic_libpath: trying "/opt//…/ent-10/lib/pg_pathman.so"
> ОТЛАДКА:  find_in_dynamic_libpath: trying "/opt/…/ent-10/lib/pg_pathman"
> find_in_dynamic_libpath: trying "/opt/…/ent-10/lib/pg_pathman.so"
> PrepareTransaction(1) name: unnamed; blockState: PREPARE; state: INPROGR, xid/subid/cid: 6919/1/40
> StartTransaction(1) name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0
> switched to timeline 1 valid until 0/0
…
Transaction MTM-1-13604-7-612438856339841 (6919) is aborted on node 2. Check its log to see error details.
...
[MTM] 28295: REMOTE begin abort transaction 7017
…
[MTM] 28295: send ABORT notification for transaction  (6919) local xid=7017 to coordinator 1

Что это за ошибки, вы сможете узнать в техподдержке, не зря же вы её покупали.

Что делать? Правильно! Обновлять до «Postgres Pro Enterprise» до v 11.2

Отдельно надо знать, что sequence, являясь объектом реплицируемой БД, отнюдь не имеет сквозное значение по всему кластеру, каждый sequence локальный для каждого узла и если у вас есть поля с уникальными ограничениями и используют sequence, то вы можете только сделать инкремент эквивалентный номеру узла в кластере, т.к. сколько узлов в кластере на столько быстрее у вас будет прирастать и sequence, да int кончится быстрее, чем вы рассчитывали. Для упрощения работы с sequence в продукте вы найдёте даже функцию alter_sequences, которая сделает нужные инкременты по каждому sequnce на всех узлах, но будьте готовы, что функция не во всех версиях будет работать. Конечно её можно написать самим, взяв за основу код с github или поправив самостоятельно прямо в СУБД. При этом поля с типом serial\bigserial будут работать более корректно, но для их использования скорее всего вам надо переписывать код ваших процедур и функций. Возможно кому-то будет полезна функция monotonic_sequences.

До версии 11.2 «Postgres Pro Enterprise» репликация будет работать только при наличии уникальных первичных ключей, учитывайте это при разработке.

Отдельно хотелось бы упомянуть об особенностях работы npgsql именно в кластерном решении, эти проблемы не возникают на single node, но в мультимастере вполне себе присутствуют.
В некоторых версиях можно столкнуться с ошибкой:

Exception Details: Npgsql.PostgresException: 25001: команда SET TRANSACTION ISOLATION LEVEL 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Что можно сделать? Просто надо не использовать некоторые версии. Надо их знать, т.к. ошибка появляется не в одной версии, и даже после её первого исправления, вы можете столкнутся с ней позже. К этому тоже надо быть готовым и лучше все выявленные дефекты СУБД, которые исправляет производитель, покрывать отдельными регрессионными тестами. Так сказать, доверяй, но проверяй.

Если приложение использует npgsql и переключается между нодами думая, что они прям все одинаковые, то у вас может возникать ошибка:

EXCEPTION:Npgsql.PostgresException (0x80004005): XX000: cache lookup failed for type ...

Такая ошибка будет происходит из-за того, что выполняется привязка

(NpgsqlConnection.GlobalTypeMapper.MapComposite<SomeType>("some_composite_type");) 

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

Как мы все знаем, общая оценка состояния кластера очень важна для диагностики и оперативных мер при работе, в продукте вы сможете найти некоторые функции, которые должны облегчать вам жизнь, но иногда они могут выдавать совсем не то, что вы и даже сам производитель от них ожидаете.

Например:

select mtm.collect_cluster_info();
на каждой ноде выдает одинаковый результат:
(1,Online,0,0,0,2,3,0,0,0,1,0,0,1,1,3,7,0,0,0,"2018-10-31 05:33:06")
(2,Online,0,0,0,2,3,0,0,0,1,0,0,1,1,3,7,0,0,0,"2018-10-31 05:33:06")
(3,Online,0,0,0,2,3,0,0,0,1,0,0,1,1,3,7,0,0,0,"2018-10-31 05:33:09")

Но почему в поле LiveNodes везде стоит число 2, хотя по описанию работы мультимастера должно соответствовать числу AllNodes=3? Ответ: надо обновить версию СУБД.

И будьте готовы собирать логи по всем узлам, т.к. обычно вы будете видеть «ошибка находится в логе другого узла». Техсаппорт примет все вами выявленные дефекты и сообщит о готовности очередной версии, которую надо будет ставить иногда и с остановом сервиса, иногда и на долго (зависит от объёма вашей СУБД). Не стоит надеется, что проблемы эксплуатации будут сильно тревожить вендора, и обновление из-за выявленных дефектов будет выполняться с участием представителей вендора, точнее даже не надо привлекать представителей вендора, так как в итоге вы можете получить на продуктиве разобранный кластер без бекапа.

Собственно, в лицензии на коммерческий продукт производитель честно предупреждает: «Данное программное обеспечение предоставляется на основе принципа «как есть» и общество с ограниченной ответственностью «Постгрес Профессиональный» не обязано предоставлять сопровождение, поддержку, обновления, расширения или изменения.»

Если вы еще не догадались про какой продукт идёт речь, то весь этот опыт был получен в результате годовой эксплуатации базы Postgres Pro Enterprise. Вывод можете сделать сами, такая сырость, что грибы вырастают.

Но это ещё бы и полбеды, если бы производилась своевременно и оперативно устранял возникающие проблемы.

Но этого то, как раз и не происходит. Видимо ресурсов у производителя не достаточно, что бы оперативно устранять выявленные баги.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Есть ли у Вас опыт перехода с иностранной/проприетарной СУБД на свободную/отечественную?
18.97% Да, положительный11
10.34% Да, отрицательный6
20.69% Нет, СУБД не меняли12
5.17% СУБД меняли, но ничего не изменилось3
44.83% Посмотреть результаты26
Проголосовали 58 пользователей. Воздержались 15 пользователей.
Теги:
Хабы:
Всего голосов 9: ↑5 и ↓4+1
Комментарии3

Публикации

Истории

Работа

Ближайшие события