Главная » Хабрахабр » Можно ли использовать Tibero вместо Oracle. И нужно ли

Можно ли использовать Tibero вместо Oracle. И нужно ли

В этой статье я расскажу вам о том, как всерьез задумался об альтернативе Oracle. А как же Postgre, скажете вы? Да, но есть нюансы. Сперва разберемся с вопросом «Почему Oracle?».
Бизнес логика у нас в БД. В книге Oracle для профессионалов Том Кайт пишет

При разработке приложений баз данных я использую очень простую мантру:

если можно, сделай это с помощью одного оператора SQL;
если это нельзя сделать с помощью одного оператора SQL, сделай это в PL/SQL;
если это нельзя сделать в PL/SQL, попытайся использовать хранимую процедуру на языке Java;
если это нельзя сделать в Java, сделай это в виде внешней процедуры на языке C;
если это нельзя реализовать в виде внешней процедуры на языке C, надо серьезно подумать, зачем это вообще делать...

и в проектировании систем я следую этому правилу. Особенно радуют объектные типы в Oracle, с их помощью сложная бизнес логика красиво и удобно реализуется по всем канонам ООП.

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

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

А нынче у них аттракцион невиданной щедрости — лицензии на Standard раздают для разработчиков практически бесплатно, за доллар на сокет. Уже несколько раз мне попадались публикации про корейский продукт Tibero, якобы создаваемый для замены Oracle. С автомобилями ведь у них, уже (почти) получилось!
Итак, разбираемся: что на данный момент могут предложить корейцы.

Описание эксперимента

Представители TMaxSoft говорят, что Tibero почти на 100% совместима с Oracle, и есть утилита для миграции базы. Я решил взять свою базу продукта, с бизнес логикой в Oracle, с использованием всей прелести ООП в PL\SQL, и перенести это в Tibero. В данной публикации мы не рассматриваем миграцию самих данных, это менее интересно, и я пока не пробовал полноценный перенос.

Задача такая:

Перенос таблиц.
2. 1. Перенос пакетов и триггеров.
4. Перенос индексов, ключей и т.п.
3. Перенос объектных типов.

Но сперва, разберемся с инструментами.

Инструменты

Гугл мало знает про Tibero. Саму базу мы скачали в виде виртуальной машины, на которой все уже развернуто. Инструмента всего два: утилита для миграции T-UP, и IDE для DBA и разработчика tbAdmin. Сделано все на Java, запускается где угодно, в теории.

T-UP выглядит примерно так:


Главное окно: коннекты к базам.


Если нажать на Options, можно кое-что настроить.


Самое главное — можно выбрать типы объектов для миграции.

Иногда она вылетала с ексепшенами, но в основном работала как надо. Никакой инструкции, помощи, подсказок обнаружить не удалось.
Производит впечатление самодельной утилиты.

Ее можно скачать с сайта TMaxSoft, если предварительно там зарегистрироваться. Второй инструмент IDE Tibero Admin. Там же можно получить демо лицензию.


Tibero Admin выглядит как типичная старенькая IDE

В Tibero Admin забудьте о контекстных подсказках, ничего не появится у вас на экране после нажатия «точечки», она не будет вам дописывать названия таблиц и объектов. Я привык к отличному инструменту PL/SQL Developer от Allround Automations. Помощь, документация? Просто печатайте код, вы ж программисты. Есть документация по СУБД на сайте производителя, интересная такая… без поиска. Нет. Впрочем, там ничего сложного. По IDE документации не обнаружено. И интересно с портами, 8630 это для SYS, для всех прочих 8629. Проблемы были с авторизацией — оказалось, пользователю нужно дать права DBA, чтоб просто зайти в tbAdmin.

Время от времени, когда куда-нибудь ткнешь, вылетают сообщение index out of bounds, очень пугает сообщение типа java.lang. IDE подглючивает. Надо учитывать разные типы окон SQL и PSM: В первом вряд ли скомпилируешь программный код, во втором — не выполнишь запрос. Exception: commitment Succeeded. После PL/SQL Developer — жалкое подобие левой руки…

Приступаем к эксперименту.

Перенос таблиц

Выбираем в T-UP схему, нажимаем Migrate, предварительно в опциях выбрав «таблицы» и начинается процесс переноса. Я столкнулся с двумя проблемами.

Я их решил перенести до таблиц, но Tibero, похоже, попытался зарезервировать под них сразу столько места, сколько они занимают в исходной базе. TABLESPACES. Табличные пространства я создал вручную, и дальше все пошло отлично. А это очень много, и он не смог.

12. Кроме таблиц с DEFAULT значениями дат типа '31. В настройках Oracle у нас данный формат прописан, для Tibero помогает 2019'.

alter session set nls_date_format='DD.MM.YYYY';

, но для T-UP такое сделать негде. Коллеги из TMaxSoft посоветовали установить переменную TB_NLS_DATE_FORMAT=«DD.MM.YYYY », но лично мне не помогло. Возможно, я что-то не так сделал. Пришлось таблицы с такими параметрами создать вручную, их не так много.

Итог первого шага: перенос структуры таблиц из Oracle в Tibero работает хорошо.

Ключи и индексы.

Выбираем галочки INDEX, CONSTRAINT в T-UP, и вперед.Проблемы возникли с CHECK из-за той же самой ситуации с датой. В целом индексы, первичные ключи, чеки — создались. А вот внешние ключи в свежесозданной базе я обнаружить не смог. И миграция констреинтов заканчивается в логе T-UP сообщением «Migration Failed: java.lang.NullPointerException». Совпадение? Не думаю…

Пакеты и триггеры.

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

Тут, к сожалению, не все прошло идеально. Поговорим о процедурах и функциях, реализующих часть логики.

Конструкция o := NEW t_my_type() не скомпилируется. Из простого: в армии Tibero нет слова NEW. Пришлось удалять. В Oracle оно, правда, не обязательное, но я всегда писал зачем-то.

Однако, при компиляции пакета или процедуры в схеме с такой ролью, при использовании таблиц и объектов другой схемы, нужно дать соответствующий grant на объект. Роль DBA позволяет в SQL Window иметь доступ ко всем таблицам. Магия роли DBA тут не помогает.

Попался мне странный FORALL в моей базе, который, однако, работает. Из специфического.


-- Пример упрощен для заметки
PROCEDURE save_tar_test AS TYPE number_table IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; TYPE date_table IS TABLE OF DATE INDEX BY BINARY_INTEGER; TYPE varchar50_table IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER; TYPE char1_table IS TABLE OF CHAR(1) INDEX BY BINARY_INTEGER; TYPE t_tar_det_out_upd_rec_test IS RECORD ( -- доп параметры cmr_tar_det_id number_table, in_stamp date_table, err_code_id number_table ); tdou_rec t_tar_det_out_upd_rec_test; BEGIN -- Это тестовый пример, тут tdou_rec не заполнен: но такой код компилируется в Oracle FORALL j IN 1 .. tdou_rec.cmr_tar_det_id.COUNT UPDATE cmr_tar_det dd SET err_code_id = tdou_rec.err_code_id(j) WHERE dd.cmr_tar_det_id = tdou_rec.cmr_tar_det_id(j) AND in_stamp = tdou_rec.in_stamp(j); END;

Tibero говорит «dml statement must have bulk-in parameter i a forall close». И я его понимаю в глубине души, но этот код пришлось переделать на обычный цикл.

Хуже ситуация с таблицами, содержащими объекты.


CREATE OR REPLACE TYPE S1.TYPE_PAY_HIST AS OBJECT
( pay_status_id NUMBER(1), stamp DATE
); CREATE OR REPLACE TYPE S1.TABLE_PAY_HIST AS VARRAY(10) OF type_pay_hist; create table S2.RECEIPT
( receipt_id NUMBER(8) not null, pay_sum NUMBER(12,2) not null, receipt_hist S1.TABLE_PAY_HIST
); FUNCTION receipt_status_change(p_cmr_receipt_id NUMBER, p_new_status NUMBER) RETURN NUMBER
AS l_receipt_hist s1.table_pay_hist; l_type_pay_hist s1.type_pay_hist; l_status NUMBER; BEGIN BEGIN SELECT receipt_hist INTO l_receipt_hist FROM receipt p WHERE p.receipt_id = p_cmr_receipt_id FOR UPDATE; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN c_err_not_find_status; END;
...
END;

Имеем ошибку при компиляции, type mistmatch.

Ребята из TMaxSoft предложили такой вариант кода:


create or replace FUNCTION ....
AS l_receipt_hist table_pay_hist; l_type_pay_hist type_pay_hist; l_status NUMBER; cmr_receipt_row cmr_receipt%rowtype;
BEGIN BEGIN SELECT * INTO cmr_receipt_row FROM cmr_receipt p WHERE p.cmr_receipt_id = p_cmr_receipt_id FOR UPDATE; SELECT TYPE_PAY_HIST(r.pay_status_id,r.stamp) bulk collect INTO l_receipt_hist FROM cmr_receipt p,table(p.receipt_hist) r WHERE p.cmr_receipt_id = p_cmr_receipt_id; EXCEPTION WHEN NO_DATA_FOUND THEN dbms_output.put_line('NO_DATA_FOUND'); RETURN null;--c_err_not_find_status; END; ...
END;

Работать оно, наверное, работает. Но не так удобно, и придется переделывать код.

И, кстати, в Tibero есть аналог. Остальное — скомпилировалось нормально, если не считать специфические вещи типа SDO_GEOM. До его изучения руки еще не дошли.

Типы

В одном из проектов мы используем мощь ООП by Oracle на полую катушку.
Самый волнующий вопрос к Tibero был именно про это.

Создаем некий тип, являющийся базовым для набора других типов.


CREATE OR REPLACE TYPE t_tar_object AS OBJECT
( id NUMBER(12), smth NUMBER(12), CONSTRUCTOR FUNCTION t_tar_object RETURN SELF AS RESULT, MEMBER FUNCTION target(param IN NUMBER DEFAULT NULL) RETURN NUMBER, MEMBER FUNCTION inside(o t_tar_object) RETURN NUMBER, MEMBER FUNCTION clone RETURN t_tar_object ) NOT FINAL; -- Тело
CREATE OR REPLACE TYPE BODY t_tar_object AS CONSTRUCTOR FUNCTION t_tar_object RETURN SELF AS RESULT
AS
BEGIN RETURN;
END; MEMBER FUNCTION target(param IN NUMBER DEFAULT NULL) RETURN NUMBER
AS
BEGIN RETURN id;
END; MEMBER FUNCTION clone RETURN t_tar_object
AS
BEGIN RETURN NULL ;
END; END;

И теперь пробуем создать ему достойного наследника.

CREATE OR REPLACE TYPE t_tar_service UNDER t_tar_object
( is_virtual NUMBER(1), CONSTRUCTOR FUNCTION t_tar_service (p_serv_obj t_tar_object, p_main_id NUMBER, p_pack_id NUMBER) RETURN SELF AS RESULT, OVERRIDING MEMBER FUNCTION target(param IN NUMBER DEFAULT NULL) RETURN NUMBER, OVERRIDING MEMBER FUNCTION clone RETURN t_tar_object
) NOT FINAL;

Компилятор откажется переопределять функцию target. Вопросов к функции clone у него, при этом, не возникает. Выяснилось, что Tibero не нравится OVERRIDING, когда у метода есть параметры. Ладно, убираем слово OVERRIDING. Но это настораживает, и пишем проверочные скрипты. Пока с родительским типом.

declare o1 t_tar_object; i1 number := 100; begin o1 := t_tar_object;
o1.id := 1;
i1 := o1.target; -- dbms_output.put_line (i1) падает с ексепшеном. -- но нас так просто не смутить, пытаемся выяснить, что же находится в i1 после этих --манипуляций if i1 > 0 then
dbms_output.put_line ('big');
end if; if i1 < 0 then
dbms_output.put_line ('small');
end if; if i1 = 0 then
dbms_output.put_line ('zero');
end if; if i1 is null then
dbms_output.put_line ('null');
end if; end;

Вроде мы не оставили выбора программе, какое бы значение не приняла переменная i1, что-то должно появиться в output. Но… ничего не появляется!


Сразу вспомнил отличный фильм

Усугубляем эксперимент На этом странности не кончаются.

declare o1 t_tar_object; i1 number := 100; begin o1 := t_tar_object;
o1.id := 1;
i1 := o1.target; -- Не важно, что было раньше в переменной - зададим ей значение
i1 := 2; if i1 > 0 then
dbms_output.put_line ('big');
end if; if i1 < 0 then
dbms_output.put_line ('small');
end if; if i1 = 0 then
dbms_output.put_line ('zero');
end if; if i1 is null then
dbms_output.put_line ('null');
end if; end;

Даже то, что после всех манипуляций с методами объекта, мы жестко задали значение переменной, ничего не меняет — output пустой.

Контрольный эксперимент, проверить себя на маразм:


declare o1 t_tar_object; i1 number ; begin o1 := t_tar_object;
o1.id := 1;
--i1 := o1.target; закомментируем эту строчку i1 := 2; if i1 > 0 then
dbms_output.put_line ('big');
end if; if i1 < 0 then
dbms_output.put_line ('small');
end if; if i1 = 0 then
dbms_output.put_line ('zero');
end if; if i1 is null then
dbms_output.put_line ('null');
end if; end;

В аутпуте появляется заветное «big». Жутковато, не правда ли? Методом научного тыка ребята из TMaxSoft выяснили, что если убрать из спецификации t_tar_object нюанс «NOT FINAL», то объект будет вести себя адекватно. Но зачем он тогда вообще нужен такой… без наследников.

Как и, собственно, ООП в Tibero. Дальше про ООП в Tibero рассказывать смысла нет. Я пока не знаю. После этого возникает и другой вопрос: а тот код процедур и функций, который скомпилировался — работает ли корректно? Для проекта, не содержащего вышеописанных упражнений с типами, это однозначный успех. Смигрировалось и скомпилировалось огромное количество кода. И честно говоря, я не ожидал, что с ней столкнусь. Но тестировать правильность исполнения кода — серьезная задача. Но если и будет, то разработка будет происходить на Oracle, с использованием нормальных удобных инструментов, и с регулярной миграцией на Tibero. Будет ли у меня проект на этой СУБД, пока сказать не готов. Писать код в IDE без контекстных подсказок и с периодическими ошибками самого интерфейса — удовольствие ниже среднего.

Выводы

Есть ли будущее у Tibero в его нынешнем состоянии? Не уверен. Ведь если поискать стоимость лицензий без учета мегаскидки, то один сокет Standard стоит порядка 800 000. Что дешевле чем Oracle, но не в разы. А как я убедился на своем опыте, пока что это даже рядом не Oracle.

Возможно, да. Есть ли смысл использовать почти бесплатный Tibero, который предлагают сейчас? Если у вас имеется в наличии команда ораклистов, и надо что-то не слишком мудреное создать и разместить на своем сервере, да подешевле и побыстрее — интересный вариант. Говорят, при оплате стоимости технической поддержки (99000 рублей в год на сокет), разрешается использовать эту базу в коммерческих проектах. Можно еще разыгрывать карту санкций, заявляя беспокойным заказчикам, что Корея это не США.

Ни за что. Переводить ли действующие проекты с Oracle на Tibero? Проще отказаться от технической поддержки Oracle, и никому ничего не платить. Нет ни одной причины искать себе такие приключения.

И как следствие, покупать новые лицензии? А если надо создать новый инстанс старого проекта, работающего на Oracle? Не исключено, что ваша база качественно смигрируется и будет работать. А вот здесь подумайте. Считаем трудозатраты, риски, выгоду от более дешевых лицензий. Но сразу задумайтесь о поддержке двух направлений в проекте, либо переводить все на Tibero. Сравниваем, решаем.

Надо лишь допилить типы, сделать нормальную IDE, может быть изменить ценовую политику. Быть может, в следующей версии Tibero все будет иначе. Будем посмотреть. И если с СУБД будет как с автомобилями, то лет через 5 корейцы могут занять существенную долю рынка и потеснить гегемона.

P.S.

Серьезным плюсом при выборе СУБД для нового проекта может стать работа тех.поддержки TMaxSoft. Я ведь даже еще лицензии за один доллар не купил, а ребята мне отвечали очень оперативно, явно заинтересованно. Помогали как с глупыми вопросами, так и с теми, что описаны здесь. Обратная связь отличная.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Как в Сингапуре работают с инновациями: от госрегулирования до ночных клубов

Привет, Хабр! Меня зовут Сергей Лукашкин, я директор по управлению проектами в управлении цифровой трансформации ДИТ ВТБ. Много лет занимаюсь финтехом и инновациями в финансовой сфере. Конечно, уделяю много времени изучению лучших российских и зарубежных финтех-практик. В мире есть несколько ...

[Из песочницы] Ticket to Ride.Европа — скромные шаги в арифметику игры

День первый. Нам подарили игру «Ticket to ride. Европа». Это моё первое знакомство с игрой данной серии, надо обязательно попробовать и заценить. Как-то надоело регулярно проигрывать, пора бы призвать на помощь математику и попробовать таким образом одержать заслуженную победу. День ...