Реінжинірінг (міграція) баз даних

 

Багатотиражні рішення розробляються для підприємств різного масштабу й для широкого кола клієнтів, кожний з яких має свої переваги. Навіть якщо вести розробку відповідно до вимог окремої фірми, цілком може виникнути необхідність у застосуванні різних серверів. Скажемо, у територіально-розподіленій компанії центральний офіс може працювати на платформі Oracle, філії, що оперують меншими обсягами даних та мають не дуже багато співробітників,— MS SQL Server, а мобільні користувачі — MS SQL Desktop або Sybase.

 

Фундаментальні роботи дослідників IBM лягли в основу мови SQL, який став стандартом для реляційних баз даних. Крім того, як мінімум три значимі специфікації SQL були підготовлені в ANSI, але жодна з них не задовольняє всім вимогам розроблювачів і користувачів для більш-менш складної обробки даних. Досить зрівняти довгий список реалізованих на різних серверах математичних, строкових, фінансових і інших функцій з коротким переліком можливостей, декларованих у стандарті ANSI.

 

Якщо неухильно додержуватися стандартів, можна зіштовхнутися із проблемою продуктивності, і виникне потрба звертатися до спеціальних функцій, які забезпечуються постачальником платформи. Приміром, Oracle для збережених процедур і сценаріїв застосовує власна мова PL/SQL, а Microsoft ще із часів спільної роботи з Sybase використовує Transact-sql або T-SQL. Побічний ефект — несумісність рішень, що означає для споживачів або вибір на користь конкретної платформи, або програмування з орієнтацією на кілька серверів баз даних.

 

Специфічні для кожного із серверів баз даних логічна й фізична організація зберігання даних, відповідний набір операторів і команд для керування сервером і об'єктами бази даних. Так, для Oracle - це datafiles, tablespaces і schemes, у той час як в SQL Server такого набору операторів немає.

 

Можливі наступні типи розбіжностей при роботі з різними СКБД:

· логічна й фізична організація зберігання даних (розподіл таблиць, індексів і інших об'єктів бази по файлах, областях, пакетах, власникам, схемам і т.п.);

· аутентифікація, розподіл прав доступу й система безпеки (користувачі, групи, ролі);

· структура баз даних (типи даних і розміри полів, обмеження на поля, індекси й т.п.);

· посилальна цілісність (первинні й зовнішні ключі, посилання між таблицями);

· програмування тригерів, збережених процедур і користувацьких функцій (вбудовані мови програмування сценаріїв), SQL-запити, команди й оператори (підтримка рівня ANSI, конструкції запитів, вбудовані функції й т.п.);

· перетворення даних (обробка порожніх полів і значень NULL, конвертація дат у числа або рядків у числа й т.п.);

· програмний інтерфейс клієнтської частини для прямого доступу до програм, що становлять СУБД, наприклад, Oracle Call Interface (підтримка зв'язаних змінних, обробка масивів записів у пакетному режимі, обробка результатів запитів);

· драйвери верхнього рівня (інтерфейси ODBC, JDBC, OLEDB, ADO, DAO);

· підтримка транзакцій (однофазних і двофазних, протоколу XA і т.п.);

· адміністрування й супровід сервера, резервні копії, оптимізація продуктивності й масштабованості, балансування навантаження;

· підтримка нижчерівневої операційної системи — клони Unix (Sun Solaris, HP-UX, IBM AIX, Linux) і Windows, протокол взаємодії клієнта із сервером і підтримка транспортного рівня (TCP/IP, IPX/SPX, Netbios).

 

Застосовуючи ті або інші мови програмування, середовища й інструменти розробки, готові компоненти третіх фірм і модулі, що поставляються виробником сервера баз даних, можна абстрагуватися від частини перерахованих типів відмінностей, але не від усіх. Наприклад, драйвери ODBC і OLEDB «третіх» виробників (таких як Merant/Intersolv або Openlink) хоча абияк і дозволяють працювати з базою, але не гарантують відсутності проблем при обробці специфічних запитів.

 

Перш ніж говорити про міграцію баз даних, розглянемо ситуацію, у якій потрібно під час виконання додатка підтримувати відразу кілька серверів баз даних. У цьому випадку можна застосовувати наступні три підходи :

1. Загальний (розгалужений) код для різних джерел даних. Специфіка враховується за рахунок розгалуженого коду, а також через константи, функції, успадковані класи й інші можливості мови програмування.

2. Один компонент (єдина точка) для різних джерел даних. Програма цілком розробляється з орієнтацією на одну із СУБД або певний стандарт, абстрактний рівень, а специфіка враховується за рахунок перехоплення підготовлених текстів запитів і звертання до драйверів доступу до бази в єдиній точці обробки запитів.

3. Багато компонентів (специфічний код) для різних джерел даних. Шар додатка, відповідальний за взаємодію з базою даних, повністю виділений; для кожного сервера баз даних застосовується свій компонент із загальними вхідними й вихідними параметрами й різною реалізацією.

 

На стадії проектування в контексті всього додатка легше оперувати одним компонентом або частиною програми, відповідальної за взаємодію із джерелом даних. Звичайно, можна спроектувати й реалізувати модуль для роботи з одним із серверів баз даних, а потім клонувати специфічний код для інших. Однак, якщо різні групи програмістів відповідають за певні модулі, або вони розробляються в різний час, велика ймовірність невідповідності реалізацій.

 

Якщо застосовувати розгалужений код, він втрачає стрункість, займає в скомпільованому вигляді більше місця й стає важким у підтримці й налагодженні. Розроблювачам складно синхронізувати зміни, створюючи кілька модулів для СКБД різних постачальників. Це також доставляє незручності адміністраторам і супровідному персоналу. Відносно оптимізації окремі компоненти ефективніше, а використання розгалуженого коду обумовлює втрати продуктивності на численних перевірках, ціль яких полягає в з'ясуванні того, для якого саме сервера складається запит, або дані з якого джерела обробляються.

 

Жоден з підходів не має явних переваг, але деякі рекомендації з їхнього використання дати все-таки можна. При наявності готового й налагодженого програмного коду, який працює з одним сервером бази даних і повинен бути модифікований для взаємодії з іншим, варіант із розгалуженим кодом кращий (особливо якщо ісходний текст не був добре структурований, розділений на шари, компоненти і т.д.).

 

Інший випадок: успадкований код настільки складний і заплутаний, що не вдається включити в нього розгалуження, або логіка базується на динамічній побудові запитів. Тоді можна знайти точки сходження програми й, скориставшись підходом з єдиною точкою обробки запитів, вмонтувати в неї алгоритм розбору побудованого запиту й реорганізації цього запиту під інший сервер бази даних. Розробка подібних аналізаторів запитів — завдання непросте. Для її розв'язку потрібні додатковий процесорний час і ретельне тестування, які також не гарантують стовідсоткової сумісності з оригінальним варіантом. Але часом це — єдина можливість забезпечити підтримку іншого сервера баз даних.

 

Застосування CASE-засобів і ERD-нотацій (Entity-Relationship Diagrams — діаграми « сутність-зв'язок») скорочує зусилля по підтримці різних серверів баз даних або їх перенесенню на іншу платформу, але не варто покладатися на штатні засоби генерації структури, тригери й процедури, призначені для конкретної СКБД. Результат генерації CASE-засобів необхідно перевіряти й коректувати «вручну». Потужні інструмент класу Powerdesigner або Erwin дозволяють набудовувати логіку генерації логічної схеми бази на фізичні об'єкти з урахуванням конкретного цільового сервера.

 

На етапі проектування слід звернути увагу на іменування об'єктів бази даних. Такі параметри, як довжина імені, наявність у ньому цифр і специфічних символів, можуть виявитися причиною серйозних проблем. Якщо SQL Server підтримує імена довжиною до 128 символів, то Oracle за замовчуванням — не більш ніж до 18 (інакше необхідно використовувати лапки), а DB2 — до 8 для ОС AIX.

 

Забезпечення цілісності даних вимагає додаткових операцій і об'єктів. Приміром, для підтримки первинних і зовнішніх ключів потрібно створювати індекси з тими ж ключовими вираженнями у відповідних стовпцях або групах стовпців. Деякі сервери баз даних не підтримують каскадні операції ( зокрема, каскадне видалення залежних записів), що приводить до необхідності написання тригерів і процедур обробки операцій зміни й видалення даних у головній таблиці.

 

Звичайно проектувальники й програмісти намагаються відкласти «на потім» логічний і фізичний розподіл об'єктів бази даних по файлах, пакетах, областях, схемам і власникам. Але, залежно від типу сервера і його функцій, такий розподіл може зіграти серйозну роль у забезпеченні безпеки, продуктивності, масштабованості й навіть сумісності з іншими додатками, якщо вони експлуатуються на тому ж фізичному сервері, що й база даних. Простий приклад: якщо створювати за замовчуванням таблиці, кожна СКБД буде виділяти певний часовий квант під їхнє початкове розміщення й наступний ріст. Якщо ж два додатки спробують створити таблиці з тим самим іменем, виникне конфлікт.

 

Типи, розміри й точність даних, навіть зазначені в стандарті ANSI, різняться в реалізації кожного сервера баз даних; відповідно, при роботі з ними система буде поводитися неоднозначно. Саме складне — обробка даних великого розміру, а також бінарних і текстових (image і text в MS SQL Server; LONG, BLOB і CLOB в Oracle і т.д.). Для кожного сервера характерні свій підхід, свої обмеження, свій набір функцій. Так, в SQL Server є окремий сервіс MS Search, що забезпечує функції Full-Text Search, а Oracle пропонує пакет PLSQL. Інший приклад: SQL Server оперує окремими адміністративними функціями при заповненні списку шумових слів (noise words) для кожної з мов за допомогою імпорту із зовнішніх файлів, а аналогічна функція в Oracle (stop words) доступна тільки для однієї мови й зберігається в системних таблицях з доступом через представлення CTX_STOPWORDS. Такі функції вимагають допоміжних спеціальних індексів, для створення яких SQL Server використовує системну процедуру sp_fulltext_table, а Oracle — спеціальний тип CTXSYS.CONTEXT і процеси job.

 

Кожний сервер баз даних містить свої системні поля, які можуть бути корисними при розробці певних алгоритмів, але стануть каменем спотикання при міграції на інший сервер. Приміром, генерація значень для ключів і кодів за допомогою IDENTITYCOL в SQL Server має аналог в Oracle у вигляді окремих об'єктів-нумераторів SEQUENCE; в інших СКБД при генерації наступного значення послідовності необхідно реалізовувати складний механізм із тригерами, додатковими таблицями й алгоритмами розв'язання конфлікту блокування. Ще один приклад: унікальний ідентифікатор записи, по-своєму інтерпретуємий серверами баз даних (скажемо, ROWID в Oracle і DB2). Для одного сервера цей ідентифікатор свідчить про фізичне розташування рядка й міняється при реорганізації зберігання таблиць, у той час як для іншого — означає версію рядка, міняється при кожній операції INSERT, UPDATE і DELETE над даним рядком і може використовуватися в запитах поряд з первинними ключами для визначення того, чи не мінявся запис.

 

У корені різняться мови програмування скриптів, тригерів, збережених процедур і користувацьких функцій. Якщо для Oracle - це PL/SQL, для MS SQL Server — T-SQL, то IBM DB2 і зовсім оперує модулем, скомпільованим за допомогою зовнішнього компілятора. Останнім часом деякі виробники стали застосовувати віртуальні Java-машини для створення збережених процедур, але їх сумісність зі специфікаціями Java — різна.

 

Мабуть, переписування логіки, реалізованої на рівні сервера бази даних у вигляді скриптів, — найбільш трудомісткий процес у проектах перенесення. По-перше, це просто різні мови програмування зі своїми операторами, правилами іменування, областю видимості змінних і т.п. Правила обробки подій тригерами, залежність від моменту зміни даних, групова обробка рядків таблиць і інші особливості можуть вплинути на обробку даних у фоновому режимі. Збережені процедури й користувацькі функції, способи передачі параметрів і повернення результатів — усе це впливає на клієнтські додатки.

 

Інформаційні системи масштабу підприємства повинні бути надійно захищені, а тому в них слід забезпечувати поділ доступу до даних. Однак, через пробіл у стандартах на відкуп виробникам СКБД віддана організація керування користувачами і їх профілями, визначення груп і ролей, а також розподіл привілеїв. В Oracle є досить розвинена власна система аутентифікації й авторизації користувачів, з деякими обмеженнями можлива підтримка операційної системи ( приміром, тільки аутентифікація в Windows), у той час як DB2 цілком покладається на ОС, і, як наслідок, реалізації для AIX і Solaris різняться. MS SQL Server може застосовувати як вбудовану авторизацію окремих користувачів і їх груп, так і інтегровану з Windows NT або Active Directory.

 

Нарешті, різниця в реалізації стандарту SQL: це синтаксис SQL-виражень (наприклад, зовнішні з'єднання outer join, «+» в Oracle і LEFT JOIN в SQL Server), конструкції SQL-запитів (наприклад, вкладені підзапити) і т.д. Нюанси можуть виявитися в обробці значень порожнього поля й NULL-значення ( при сортуванні рядків один сервер поміщає порожні рядки в початок, а інший — у кінець результуючої безлічі). По-різному інтерпретуються й правила перетворення даних у різних системах. Деякі програмісти люблять покладатися на «умовчання» — і дарма: якщо один сервер дозволяє використовувати операнди різних типів і приводить їх до єдиного знаменника, то інший генерує помилку.

Кожний виробник забезпечує свою СКБД певним числом вбудованих системних функцій, змінних, процедур і ключових слів. Найпростіший приклад — одержання системної дати в SQL-вираженнях: виклик функції GETDATE () в SQL Server, вставка ключових слів CURRENT DATETIME в IBM DB2 і SYSDATE в Oracle. Більш складний приклад — обробка повнотекстового пошуку. Для обробки об'єктів великого розміру ( текстових полів) Oracle поставляє окремий пакет interMediaText, який додається в пакет PL/SQL разом з набором функцій, а в SQL Server — це окремий компонент MS Search.

Багато розроблювачів і адміністратори застосовують SQL-сценарії для виконання ініціалізующих і регулярних дій — створення бази даних, формування логічної й фізичної структури бази, наповнення її вихідними даними, визначення груп і ролей користувачів, і т.д. Правила складання сценаріїв встановлюються кожним постачальником по-своєму.

І останнє, що не піддається опису кількома словами, — це забезпечуваний при реалізації проекту рівень продуктивності, масштабованості, надійності, продуктивності, ефективності. Занадто багато факторів впливають на ці параметри, щоб заздалегідь бути впевненим у кінцевих результатах проекту перенесення. Практичний досвід, знання специфіки кожного із серверів баз даних, базового апаратного й програмного забезпечення, уміння настроїти параметри, будувати розподілену інфраструктуру й балансувати навантаження, вивчати план виконання запиту й оптимізувати його за рахунок реструктуризації й створення індексу — усе це й багато чого іншого дозволяє одержати заданий результат.

Висновок

Як говорить стара істина, «хто попереджений, той озбройний». Сподіваємося, тепер керівники проектів і провідні проектувальники, розроблювачі й фахівці із забезпечення якості, що займаються реінжинірингом додатків, зможуть краще представити « бойовище» і оцінити обсяг необхідної роботи.