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

Комментарии 54

НЛО прилетело и опубликовало эту надпись здесь

плюются пока не начали мигрировать на pg ))) Сразу начнут отхаркивать. Одно делать переносить самописные апликухи, которые к тому же не используют процедурный код, как пишет автор, другое делать переписать процессинг или абс

НЛО прилетело и опубликовало эту надпись здесь

Та вроде на гринплам уже собрались переползать... К 23 году аналитическое хранилище перетащить, а потом и прод в отдаленной перспективе. Но это не точно :)

В Сбере тоже есть адекватные менеджеры и миграция с Oracle на PG идет полным ходом, в ближайшем времени постараемся опубликовать статью с нашим опытом.

Сдается мне, на многих АС сбер никогда не слезет с Oracle. Когда почти весь бэк в Oracle пересесть с него очень сложно. Тут или останавливать разработку новых фич на N лет, либо нанимать 3х людей от текущей команды, чтобы наверстать все упущенное и не отставать. Это банально дорого.
Вот только фи за строгую типизацию не надо тут разводить. «лепить» намбер — это именно «лепить»
Ну тут опосредованно. На самом деле это намного более хорошо, что она строгая в пг, но в данном конкретном случае — она привнесла больше всего проблем. С третьей стороны — SQL язык с историей, как мне кажется он проектировался «с нестрогой типизацией», а там дальше уже как у кого пошло ;)

Запуск приложений у нас оформлен как сервисы (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
В некоторых случаях подхватывался файл настроек (этот вот отдельный) в некоторых нет. Причем если просто из командной строки — то, например, да, если из сервиса, то, например, нет.
Короче говоря оставили в сервисе тот вариант, который «сработал» (в результате экспериментов). И так — ок.

Очень странно. Особенно с учётом того, что конфиг по абсолютному пути читается. Больше похоже на то, что у корневых процессов шелла и джавы разные права в итоге получаются. По идее где-то тогда должно быть видно AccessDeniedException или что-то в таком духе.

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 и посмотрел что делает джарник - он же начинается с баш скрипта, где-то там точно можно найти в чем дело. Чисто из академического интереса выяснить на чем он падает.

файл же исполняемый?

Да, исполняемый. Спасибо за советы, дойдут руки — докопаюсь. Мне нравится разбираться в природе вещей. То, что JAR может быть полутекстовым для меня стало открытием и именно на этом проекте.
Да, исполняемый. Спасибо за советы, дойдут руки — докопаюсь. Мне нравится разбираться в природе вещей. То, что JAR может быть полутекстовым для меня стало открытием и именно на этом проекте.
баш запускается из любого каталога, это значит, что в 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.
О, прикольно! Т.е. можно в эти папки симлинк набросить и он его «почувствует». Да, вероятно это вариант, проверю при случае.
Имхо, лучше использовать абсолютные пути, а не подпирать костылями.
вы правы, я просто имел ввиду мысль чтобы понимать физику процесса. Мы то как столкнулись с этим — «там» работает (rhel), «тут» нет (redos). И сидим думаем, какое решение предпринять. Но объяснение выше в целом дает понимание полностью.

Если не изменяет память, то с поддержкой вам должна быть доступна функция онлайн репликации в PG из коробки. Зачем самим что то придумывать.

В целом статья интересная. PG развивается достаточно динамично и старается догнать Ora и MS. Начни вы мигрировать на условную 10ку несколько лет назад, все было бы печальнее.

Вот чего очень не хватает в Постгрессе это аналога агрегатных функций KEEP как в Oracle. Приходится делать на аналитических функциях, но это очень плохая замена.
А есть в оракле агрегаты с filter? Я не помню, но мне тоже эта фича в пг понравилась.
Тут например описано: habr.com/ru/company/tensor/blog/507056

SELECT
count(*) FILTER(WHERE prime < 10) countlt
, count(*) FILTER(WHERE prime > 10) countgt
FROM…

Только не говорите, что можно sum(case( использовать, это я знаю ;) тут все же изящнее и по моему возможностей больше
Проблема в том, что на FILTER есть аналог — CASE, а на KEEP аналога нет.
А кто изящнее выглядит — это больше вкусовщина.

Ну я бы ваш запрос переписал как-то так:

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. Есть и другие агрегирующие функции, можно через несколько функций вообще страшную магию делать. В это плане у постгреса всё хорошо.

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

Теперь понятно. Вы просто это не уточнили, потому меня смутила фраза

Спасибо за подробную статью. А с производительностью что-нибудь делали? К примеру всякие механизмы обработки блокировок в Оракле должны по другому работать, и протестировать это сложнее

Да нет, пока только запустились. Вроде все шевелится также (интерфейс), да, пока видимо что немного помедленнее, но решили заменить SAS диски на SSD, после чего еще раз посмотрим. Тонкий тюнинг будем делать когда все номинально запустится в полном объеме, а то попадаются разделы приложения, которые нужно «шлифовать» (исправлять запросы и т.д.).
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. Так что может быть разница, если в оракле писали с учетом его особенностей работы пустых строк.

Вы мне напомнили старую байку, как какой то шутник в дебрях сишного проекта переопределил в дефайнах true = false и наоборот. У вас очень классный комментарий, я этого не знал. Но на мой взгляд, этим заниматься не стоит — мы же не эмулируем оракл со всей его внутрянкой (несмотря на orafce), а все таки пытаемся с него смигрировать — так или иначе, с допущениями, нужно принимать философию той БД, на которую мы переходим, тем более она более стройная (по крайней мере в этом месте).

Сколько слов в статье, перешли с оракла на pg, вах...

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

И самое главное: это бизнес-критикал база? Под бизнес-критикал я имею виду, что потеря даже 1 транзакции может обернуться колоссальными убытками для компании. Ну например база банковского процессинга - это бизнес-критикал, потеряли транзакцию с переводом 100 млрд.р. - это хана. А вот база с каким-нибудь чатиком тех.подержки , где лежат котики - это... ну сами понимаете, фигня, а не база.

а база хелпдеска, например? )

Доброго дня! вы так это сказали, что как будто бы база окажется не большой и не очень важной, то это будет обидно для вас и как минимум обесценит весь наш труд ;)

Так или иначе, мы выделяем следующие классы систем:

Mission critical - Критически важные ИТ-системы/ платформы, нарушения в работе которых приводит к существенным невосполнимым потерям и серьезно затрагивает ключевые бизнес-процессы даже в краткосрочном периоде

Business critical - Критически важные ИТ-системы/ платформы для бизнеса, выход из строя которых приводит к серьезным потерям для бизнеса, однако в краткосрочном периоде ключевые бизнес-процессы могут осуществляться с незначительным снижением уровня сервиса

Business Operational - ИТ-системы, выход из строя которых затрагивает только внутренние процессы и не приводит к потерям в среднесрочном периоде, в долгосрочном периоде создаются существенные неудобства пользователям

Office Production - Некритичные ИТ-системы, простой которых в среднесрочном периоде не влияет на бизнес-процессы

В статье идет речь про Business Operational систему. И да, база не очень большая, около 300Gb (размер в ora и pg примерно одинаков), основной поток данных - интеграционный и в результате работы фоновых процессов (расчетов), т.е. точечных "небольших" вводов данных (пользовательских) не много, больше сосредоточено на сбор данных из внешних систем (можно сказать, что система аналитическая). Партиционирование есть на крупных таблицах, но его немного.

Ответил я на ваши вопросы? ;)

Спасибо за ответы.

Про количество обрабатываемых транзакций в секунду не написали, это кстати важный показатель.

Да я, честно говоря, не замерял. Думаю не много. Основная загрузка и расчет — по ночам (там пачками и по многу). Потом пользователи в основном только смотрят рассчитанные показатели, объем пользовательского ввода невелик.
А для миграции то зачем такая хирургическая точность? Ведь главное смигрировать (окончательно) в тот момент, когда мы вреда не нанесем. День-два простоя системы нам дадут, больше — вряд ли. Мы уложимся.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий