Миграция С Sql Server На Mariadb/Mysql. Что Делать С Xml

Коллеги, хотел бы предложить вам описание решений, которые помогли в проекте миграции большого приложения с SQL Server на MariaDB/MySQL. Возможно, это поможет кому-то в подобном проекте.



Что мы не сделали

Функционал MariaDb/MySQL, скажем так.

меньше, чем у SQL Server, но в этом проекте мне не пришлось сталкиваться с такими аспектами, как:

  • миграция аналитики, построенной на базе SSAS;
  • или процессы ETL с использованием SSIS;
  • Полнотекстовый поиск уже реализован на Apache SOLR (как и должно быть сделано).



Что мы сделали

  • Была схема на 150 таблиц и ~20 представлений;
  • > 900 процедур;
  • рекурсивный CTE (рекурсивные общие табличные выражения);
  • работа с XML;
  • табличные параметры;
  • динамический SQL;
  • аналитические функции (например — ROW_NUMBER() OVER()), которых нет в MariaDb, но иногда всё же можно что-то сделать.

    ;

  • и, конечно же, UNIQIDENTIFIER в качестве кластерного индекса для значительной части таблиц (и почему некоторые разработчики так любят этот тип данных?
Пришлось решать проблемы с производительностью и искать причины взаимоблокировок, с чем я помог Набор инструментов Перкона .

А также модифицируем DAC (уровень доступа к данным), чтобы приложение работало с SQL Server и MariaDb.

Основные проблемы

Самой большой проблемой было преобразование процедур просто потому, что их было очень много.

Никто всерьез не рассматривал возможность перехода на NHybernate или другой ORM; процедуры были полны логики и переносить ее на бизнес-уровень никто не собирался (вы уже правильно догадались, что приложение на .

NET).



Что было хорошо

Принципиальная осуществимость проекта заключалась в том, что синтаксис T-SQL и синтаксис процедур MariaDb/MySQL аналогичны и существовала теоретическая возможность автоматизации процедур преобразования.

По крайней мере, для тривиальных случаев CRUD. Мне особенно понравилось то, что из процедур в MariaDb/MySQL можно возвращать несколько наборов результатов, как и в T-SQL. Мне всегда было интересно, почему разработчики Oracle или PostgreSQL не предоставили такую простую функцию.

То есть простой оператор SELECT * FROMusers в конце процедуры приводит к чтению ее результата в DAC на стороне клиента.

Причём это может быть любое количество операторов SELECT, не перенаправленных в таблицу (INSERT INTO.SELECT) или в переменную (SELECT.INTO.) и даже не обязательно в конце процедуры.

И конечно, помогли написанные ранее интеграционные тесты.

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

Чем больше охват тестов функциональности ЦАП, тем больше вероятность того, что проект будет успешным.

Кстати, MySQL и MariaDb можно установить и на Windows, но лучше начинать разработку непосредственно на Linux. В Linux есть более качественная инструментальная среда (вроде того же Percona Toolkit) и вы сразу столкнетесь с проблемой корректной сортировки идентификаторов, а точнее имен таблиц.

Например, в Linux запрос SELECT * FROM users и SELECT * FROM Users — это совсем не одно и то же.

Поскольку данные таблицы находятся в файлах, а в Unix/Linux файловая система чувствительна к регистру.

И, что неудивительно, MariaDb работает быстрее внутри виртуальной машины Linux, чем на хосте Windows в качестве «родной» службы Windows. Судя по всему, MySQL не имеет ничего общего с этой замечательной настольной операционной системой.



Начнем с самого простого — что делать с XML?

Приложение использовало XML следующим образом:
  • Передается как параметры процедуры и возвращается в наборах результатов.

    Решение простое: мы используем тип данных LONGTEXT вместо XML, с Oracle MySQL NET Connector все работает нормально.

  • Извлечено из параметров сбора данных XML. Это был подход в коде, и он использовался вместе со списками, разделенными запятыми, и параметрами с табличными значениями ( https://msdn.microsoft.com/en-us/library/bb510489.aspx ) где и как, история продукта была долгая.

  • Использовались конструкции вида SELECT .

    FOR XML.

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

    Конструкции типа –UPDATE table1 SET field1.modify(.

    )

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



Сбор данных в параметрах XML

Вообще в MariaDb/MySQL есть функция ExtractValue, которая может выполнять XPath для XML-документа, переданного в параметрах как BLOB, и возвращает результат в виде текста.

 SELECT ExtractValue('<a><b>Brown Seal</b></a>', '/a/b/text()')
Другой вопрос, а что, если вам дали XML-документ, содержащий некий набор значений и размеров, вы об этом не знаете? Как определить, сколько элементов в коллекции? А как удалить конкретный элемент коллекции? Для подсчета элементов в XPath существует функция count(), которая может возвращать количество элементов XML, соответствующих определенному выражению XPath. ( http://www.w3schools.com/xpath/xpath_functions.asp )
 SELECT ExtractValue('<a><b>Brown</b><b>Seal</b></a>', 'count(/a/b)')
После того, как мы определили количество элементов в коллекции, мы можем написать XPath для получения определенного элемента.

 SELECT ExtractValue('<a><b>Brown</b><b>Seal</b></a>', '/a/b[1]/text()')
и цикл для получения всех элементов коллекции.

 
 CREATE PROCEDURE `sproc1` (
Теги: #.

NET #mariadb #sql-сервер #MySQL #MySQL #.

NET

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.