Комментарии 54
плюются пока не начали мигрировать на pg ))) Сразу начнут отхаркивать. Одно делать переносить самописные апликухи, которые к тому же не используют процедурный код, как пишет автор, другое делать переписать процессинг или абс
Та вроде на гринплам уже собрались переползать... К 23 году аналитическое хранилище перетащить, а потом и прод в отдаленной перспективе. Но это не точно :)
В Сбере тоже есть адекватные менеджеры и миграция с Oracle на PG идет полным ходом, в ближайшем времени постараемся опубликовать статью с нашим опытом.
Запуск приложений у нас оформлен как сервисы (systemctl), почему то под RHEL запуск приложения работает строкой «ExecStart=/path/to/spring_boot_based.jar», тогда как под RedOS заработало только если указать «ExecStart=/bin/bash /path/to/spring_boot_based.jar».
Это, простите, то ли инфернальный по степени толщины стеб, то ли даже думать не хочется про другие варианты.
для запуска jar есть специальная программа, называется она, внезапно, java
есть специальная магия, чтобы запускать jar как обычный бинарник
https://www.kernel.org/doc/html/latest/admin-guide/java.html
но я ей никогда не пользовался, написать java -jar somefile.jar
вроде несложно.
как у вас bash запускает jar — сходу не готов ответить, скорее всего, в него встроена похожая магия.
как вам пришло в голову для исполнения jar использовать интерпретатор shell-скриптов — отдельный вопрос.
Джарники, когда они запускаются как сервисы и когда они запускаются «отдельно», как то по разному интерпретируют пути запуска. Т.е. у нас конфиги лежат в отдельных папках, сами джары — в отдельных. И мы по разному перепробовали и оно по разному подхватывает, т.е. ваш пресловутый (и самый популярный) «джава минус джар» пробовали сразу.
Теперь о том как работает магия (я сам долго не мог понять «а почему оно вообще работает»). Я разбирал этот вопрос. Сам Jar файл, как выяснилось, может быть «полутекстовым, полубинарным». Т.е. сначала в нем идет текст:
#!/bin/bash
и куча команд как это все запускается.
А потом мы уже видим начало бинарной части, с характерным идентификатором:
exit 0
PK #”йR META-INF/юК PK PK
Но вот я посмотрел другие jar файлы, из других проектов — они просто состоят из бинарной части, т.е. чистого архива. Видимо есть какой то хитрый механизм сборки (скорее всего какой нибудь плагин мавена), который «текстовую часть» (для баша) «дорисовывает».
Вот как то так.
Джарники, когда они запускаются как сервисы и когда они запускаются «отдельно», как то по разному интерпретируют пути запуска.
Не расскажете, что это значит в вашем случае?
CGroup: /system.slice/mcs-hermes.service
├─69315 /bin/bash /var/some_app/some_app.jar
└─69331 /usr/bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -Dspring.config.location=/opt/some_folder1/application.properties -jar /var/some_app/some_app.jar
Т.е. запущен jar и указан путь к файлу настроек, который лежит отдельно от jar.
И мы пробовали разные варианты запуска:
java -jar some_app.jar
bash /some_app.jar
В некоторых случаях подхватывался файл настроек (этот вот отдельный) в некоторых нет. Причем если просто из командной строки — то, например, да, если из сервиса, то, например, нет.
Короче говоря оставили в сервисе тот вариант, который «сработал» (в результате экспериментов). И так — ок.
Postgres Pro - платный продукт со своими лицензионными ограничениями. Почему про стоимость лицензий ничего не написано?
Типо в тихоря слезли с лицензионной иглы...
Ну и вообще, стоимость лицензий на PGPro — вполне себе скромна. Если посмотрите, мы специально выбрали Standard версию, которая раза в 4 дешевле Enterprise. Потому что ее в данном случае хватает.
боевая система не может быть без поддержки. это требования регулятора. Импортозамещение не предполагает переход на опенсор же.
Вообще, язык SQL очень хорошо стандартизирован
хорошая шутка. стандарт есть, конечно, но…
>>> Запуск приложений у нас оформлен как сервисы (systemctl), почему то под RHEL запуск приложения работает строкой «ExecStart=/path/to/spring_boot_based.jar», тогда как под RedOS заработало только если указать «ExecStart=/bin/bash /path/to/spring_boot_based.jar».
Посмотрите стандартный шелл для вашего аппликейшн юзера в /etc/passwd (или ldap, где он у вас там заведен), может там вместо bash стоит ksh/dash, а бутспринг в своем джарнике использует какие-то башизмы.
echo $SHELL
/bin/bash
Мне вот честно говоря это непонятно, баш запускается из любого каталога, это значит, что в path он прописан. Но при использовании в сервисе — помогло только написание полного пути. Вопрос почему? Я не знаю. Но решение найдено и оно вполне работает, поэтому — ну, пусть так и будет.
я бы просто включил отладку set -x и посмотрел что делает джарник - он же начинается с баш скрипта, где-то там точно можно найти в чем дело. Чисто из академического интереса выяснить на чем он падает.
файл же исполняемый?
баш запускается из любого каталога, это значит, что в path он прописан
У systemd своя атмосфера, он не смотрит в PATH для поиска исполняемого файла.
If the command is not a full (absolute) path, it will be resolved to a full path using a fixed search path determined at compilation time. Searched directories include /usr/local/bin/, /usr/bin/, /bin/ on systems using split /usr/bin/ and /bin/ directories, and their sbin/ counterparts on systems using split bin/ and sbin/. It is thus safe to use just the executable name in case of executables located in any of the «standard» directories, and an absolute path must be used in other cases. Using an absolute path is recommended to avoid ambiguity. Hint: this search path may be queried using systemd-path search-binaries-default.
Если не изменяет память, то с поддержкой вам должна быть доступна функция онлайн репликации в PG из коробки. Зачем самим что то придумывать.
В целом статья интересная. PG развивается достаточно динамично и старается догнать Ora и MS. Начни вы мигрировать на условную 10ку несколько лет назад, все было бы печальнее.
Тут например описано: habr.com/ru/company/tensor/blog/507056
SELECT
count(*) FILTER(WHERE prime < 10) countlt
, count(*) FILTER(WHERE prime > 10) countgt
FROM…
Только не говорите, что можно sum(case( использовать, это я знаю ;) тут все же изящнее и по моему возможностей больше
Ну я бы ваш запрос переписал как-то так:
SELECT HR.*
FROM
(
SELECT
HRX.*,
ROW_NUMBER () OVER ( ORDER BY HRX.PROCESS_DATE DESC) AS RN
FROM SOME_TABLE HRX
) HR
JOIN SOME_TABLE2 AD ON AD.ID = HR.ADDRESS_ID
JOIN SOME_TABLE_3 CH ON AD.ID = CH.ADDRESS_B_ID AND CH.ID = 517425
WHERE HR.RN = 1
AND ….
в pg нет возможности сделать listagg distinct
Есть string_agg и там есть модификатор DISTINCT. Есть и другие агрегирующие функции, можно через несколько функций вообще страшную магию делать. В это плане у постгреса всё хорошо.
Спасибо за подробную статью. А с производительностью что-нибудь делали? К примеру всякие механизмы обработки блокировок в Оракле должны по другому работать, и протестировать это сложнее
Null его ставит в тупик, так как он определяет его как unknown. Возможно, тут есть какой-то workaround, но сходу мы его не нашли.
мы эту проблему решали явным приведением типов параметров:
select * from some_function(some_param::some_type)
если hibernate отказывается есть ::, можно попробовать CAST
Это всё несомненно интересно,но как по мне под Oracle написано слишком много решений.
И я бы даже осмелился назвать Oracle стандарт ом в области интерпрайз БД.
У некоторых моих коллег какое-то нездоровое стремление смигрировать с Оракла на Постгрес, хотя Ораклом занимаются отдельная команда ДБА, платить за лицензии надо не нам, а бизнесу, тестовых стендов для любых игр и экспериментов — хватает более чем, а всё-равно «давайте перепишем, давайте перепишем». Что характерно — какие плюсы это может принести никто объяснить не может, а вот какие минусы могут вылезти в процессе — вот уже целая статья про потенциальные проблемы.
Правило, которые надо запомнить на всю жизнь: в Oracle null + some_text = some_text. Практически во всех других базах = null.
В PG можно изменять используемые операторы, как в данном случае оператор конкатенации строк || Можно сделать так, чтобы логика работы была аналогична оракловому (сложение с null не будет обнулять результат), но тут уже для себя решать, если хотите сделать полную аналогию оракловому или сохранить стандарт PG. Примерно так выглядит:
create or replace function public.concat_null(text, text)
returns text as $body$
select concat($1, $2)
$body$ language sql immutable;
create operator public.|| (leftarg = text, rightarg = text, function=concat_null);
Приоритет выбора нужной версии (оператора/функции и т.п.) настраивается через задание search_path. Соответственно нужно понизить приоритет pg_catalog перед нашими, например так (обычно еще стоит oracle от orafce)
set search_path to "$user", public, oracle, pg_catalog;
И тогда
select null||'something'
будет как в оракле возвращать строку вместо null.
nvl — просто меняем на coalesce не думая, все работает.
только в оракле есть особенность, '' и null - одно и то же, в отличие от PG. в результате в оракле nvl('', value) идентично nvl(null, value)
coalesce ожидает точного значения: или '' или null. Так что может быть разница, если в оракле писали с учетом его особенностей работы пустых строк.
Сколько слов в статье, перешли с оракла на pg, вах...
Столько важных деталей не было озвучено. Скажите, какой размер базы был на оракле? Какой стал на pg? Сколько баз мигрировали? Сколько записей было в самой крупной таблице? Сколько транзакций в секунду обрабатывала база? Было ли партиционирование таблиц?
И самое главное: это бизнес-критикал база? Под бизнес-критикал я имею виду, что потеря даже 1 транзакции может обернуться колоссальными убытками для компании. Ну например база банковского процессинга - это бизнес-критикал, потеряли транзакцию с переводом 100 млрд.р. - это хана. А вот база с каким-нибудь чатиком тех.подержки , где лежат котики - это... ну сами понимаете, фигня, а не база.
а база хелпдеска, например? )
Доброго дня! вы так это сказали, что как будто бы база окажется не большой и не очень важной, то это будет обидно для вас и как минимум обесценит весь наш труд ;)
Так или иначе, мы выделяем следующие классы систем:
Mission critical - Критически важные ИТ-системы/ платформы, нарушения в работе которых приводит к существенным невосполнимым потерям и серьезно затрагивает ключевые бизнес-процессы даже в краткосрочном периоде
Business critical - Критически важные ИТ-системы/ платформы для бизнеса, выход из строя которых приводит к серьезным потерям для бизнеса, однако в краткосрочном периоде ключевые бизнес-процессы могут осуществляться с незначительным снижением уровня сервиса
Business Operational - ИТ-системы, выход из строя которых затрагивает только внутренние процессы и не приводит к потерям в среднесрочном периоде, в долгосрочном периоде создаются существенные неудобства пользователям
Office Production - Некритичные ИТ-системы, простой которых в среднесрочном периоде не влияет на бизнес-процессы
В статье идет речь про Business Operational систему. И да, база не очень большая, около 300Gb (размер в ora и pg примерно одинаков), основной поток данных - интеграционный и в результате работы фоновых процессов (расчетов), т.е. точечных "небольших" вводов данных (пользовательских) не много, больше сосредоточено на сбор данных из внешних систем (можно сказать, что система аналитическая). Партиционирование есть на крупных таблицах, но его немного.
Ответил я на ваши вопросы? ;)
Спасибо за ответы.
Про количество обрабатываемых транзакций в секунду не написали, это кстати важный показатель.
А для миграции то зачем такая хирургическая точность? Ведь главное смигрировать (окончательно) в тот момент, когда мы вреда не нанесем. День-два простоя системы нам дадут, больше — вряд ли. Мы уложимся.
Почему мы перешли с Oracle на PostgreSQL, и как это сделать