Як безпечно запустити міграцію баз даних за допомогою декількох примірників додатків?


10

У нас є додаток, який поєднує як швидку (<1 секунду), так і повільну міграцію бази даних (> 30 секунд). Зараз ми виконуємо міграцію баз даних як частину CI, але тоді наш інструмент CI повинен знати всі рядки підключення до бази даних для нашого додатка (у різних середовищах), що не ідеально. Ми хочемо змінити цей процес, щоб програма запускала власні міграції бази даних при запуску.

Ось така ситуація:

У нас є кілька примірників цієї програми - близько 5 у виробництві. Давайте назвемо їх node1, ..., node5. Кожен додаток підключається до одного екземпляра SQL Server, і ми не використовуємо прокатні розгортання (наскільки я знаю, усі додатки розгорнуті одночасно)

Проблема: скажімо, у нас тривала міграція. У цьому випадку node1починається, потім починається виконання міграції. Тепер, node4починається, і тривала міграція ще не закінчилася, тому node4також починається запуск міграції -> можлива корупція даних? Як би ви попередили цю проблему чи проблема є навіть досить важливою, щоб хвилюватися?

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

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


1
Як щодо використання таблиці "статус міграції" як глобального / розподіленого блокування? Один рядок вказуватиме, чи є активна міграція в даний час і можливо, яка міграція була виконана останньою.
Барт ван Інген Шенау

Чи потрібно розгортати свої програми асинхронно?
Бен

Відповіді:


4

Оскільки ви згадали про SQL-сервер: згідно з цим колишнім повідомленням DBA.SE , зміни схем можуть (і повинні) бути введені в транзакції. Це дає вам можливість проектувати свої міграції так само, як і будь-яка інша форма одночасного запису у ваш БД - ви починаєте транзакцію, а коли вона не завершується, ви повертаєте її назад. Це запобігає принаймні деякі найгірші сценарії пошкодження бази даних (хоча самі транзакції не запобігають втраті даних, коли є руйнівні кроки міграції, такі як видалення стовпця або таблиці).

Поки я впевнений, що вам також знадобиться migrationsтаблиця, де вже зареєстровані застосовані міграції, щоб процес подання заявки міг перевірити, чи була застосована конкретна міграція чи ні. Потім використовуйте "ВИБІР ДЛЯ ОНОВЛЕННЯ", щоб реалізувати такі міграції (псевдокод):

  • Почніть операцію
  • SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
  • якщо колишній оператор повертає значення, закінчіть транзакцію
  • застосувати міграцію (відкатати, якщо вона не вдасться, зареєструвати помилку та припинити транзакцію)
  • INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
  • завершити транзакцію

Це будує механізм блокування безпосередньо в тест "була міграція вже застосована" .

Зауважте, що ця конструкція теоретично дозволить не знати про ваші кроки міграції, яка програма реально її застосовує - можливо, що крок 1 застосовано програмою app1, крок 2 - програмою2, крок 3 - програмою 3, крок 4 - програмою1 знову тощо. Однак також непогано застосовувати міграцію до тих пір, поки використовуються інші екземпляри додатків. Паралельне розгортання, як згадувалося у вашому запитанні, вже може спричинити це обмеження.


1

Можливо, ви можете знайти бібліотеку, яка підтримує міграцію бази даних з кількома вузлами.

Я знаю про дві бібліотеки в світі Java, обидві підтримують те, що потрібно:

  • Liquibase : з їх часто заданих питань : Liquibase використовує розподілену систему блокування, щоб дозволити одному процесу одночасно оновлювати базу даних. Інші процеси будуть просто чекати, поки замок буде звільнено.
  • Flyway : зі сторінки завантаження : безпечно для декількох вузлів паралельно ✓

Можливо, є й інші інструменти для Java та інших мов.


Якщо ви не можете (або не хочете) використовувати такий інструмент, таблицю можна використовувати як блокування або навіть як журнал міграції, див . Приклад відповіді Doc Browns .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.