Онлайн-міграція схеми MySQL: де ламається прод
Зміна структури таблиці без простою здається рутинною операцією, доки ALTER не зустрінеться з живим навантаженням. MySQL утримує метадані таблиці до кінця перебудови: поки переписуються мільйони рядків, вхідні запити чекають на звільнення блокування. Деградація сервісу під навантаженням починається раніше, ніж завершиться сама операція.
Блокування таблиць у проді — лише перша грань. Тривала перебудова тримає відкриту транзакцію та роздуває журнал відкату, а тайм-аути під час довгої перебудови рвуть обмін із репліками: відставання зростає, і частина трафіку читає застарілі дані. Користувач бачить не помилку міграції, а сервіс, що сповільнився.
Окремий клас відмов — розбіжність даних на копіях. Перебудова через таблицю-двійник і тригери переносить рядки порціями, і порція, загублена під час перемикання або конфлікту унікальних ключів, залишається лише у старій версії таблиці. Міграція виглядає успішною, а звірка лічильників показує розбіжність.
Інструмент pt-online-schema-change знімає більшу частину цих ризиків: копіює таблицю порціями, стежить за відставанням копій і перемикає дані перейменуванням.
Але поведінку задають параметри — розмір порції, пауза при відставанні, допустиме навантаження на диск; виставлені навмання, вони завалюють базу сильніше, ніж одиничний ALTER.
Онлайн-міграція схеми MySQL — керований процес, а не натискання кнопки: їй передують заміри, репетиція на копії та план відкату. Розбираємо, де саме ламається прод і як це закривається.
Що дає акуратна перебудова таблиць без зупинки
Звичайний ALTER TABLE на великій таблиці вибудовує чергу запитів за метаданими блокування: поки триває перебудова, читання й записи чекають, а на навантаженому сервісі це виглядає як сплеск тайм-аутів у клієнтів.
Перебудова таблиць без зупинки сервісу влаштована інакше: Percona Toolkit створює тіньову копію з цільовою структурою, переносить рядки порціями та синхронізує зміни через тригери, поки застосунок продовжує писати у вихідну таблицю.
Блокування залишається лише на фінальному перемиканні — коротке перейменування, яке не встигає накопичити чергу запитів. Це і є усунення відмов через блокування: клас помилок, де застосунок чекає на звільнення таблиці довше, ніж дозволяє його тайм-аут, не виникає взагалі.
Вікно обслуговування скорочується з годин планового простою до кількох секунд, і то лише за умови, що перемикання вписується в регламент.
Передбачуваний час робіт дає керована швидкість перенесення: між порціями витримується пауза, а при зростанні затримки на копії процес автоматично призупиняється.
Зниження навантаження на копії бази досягається тим самим механізмом — репліки не відстають від майстра, тому звіти й аналітика продовжують читати актуальні дані, а не наздоганяють джерело після завершення робіт.
На виході замовник отримує таблицю з цільовою структурою, план відкату, підготовлений до запуску, і журнал перенесення: обсяг рядків, точки пауз, тривалість фінальної заміни.
Терміни за великою таблицею рахуються заздалегідь за обсягом і швидкістю перенесення, а не з’ясовуються в момент простою — це і перетворює міграцію з ризику на плановану роботу.
Способи перебудувати таблицю: порівняння підходів і обмежень
Вибір способу визначається трьома параметрами: обсяг таблиці, допустимий час недоступності запису та характер навантаження.
Онлайн-перебудова через проміжну копію — це pt-online-schema-change з Percona Toolkit — створює поряд таблицю з новою структурою, копіює рядки порціями та вішає тригери на джерело, тому зміни із застосунку потрапляють одразу в обидві таблиці.
На фінальному кроці імена міняються місцями, і блокування запису вміщується в мілісекунди — зазвичай його не помічають ні користувачі, ні фонові завдання.
Межі у підходу теж конкретні. Таблиця без первинного або унікального ключа не обробляється — це відсікає частину історичних таблиць.
Копія займає стільки ж місця, скільки джерело, а при щільному записі наздоганяння змін може відставати від тригерів: тоді робота переривається, і її переносять у вікно обслуговування.
| Підхід | Коли підходить | Обмеження |
|---|---|---|
| Онлайн-перебудова через проміжну копію | Є первинний ключ, запис не можна зупиняти, таблиця живе під цілодобовим навантаженням | Копія подвоює місце, немає унікального ключа — не запускається, при щільному записі наздоганяння відстає |
| Перенесення на нову таблицю з довантаженням | Змінюється тип ключа, схема секціонування або структура переписується глибоко | Потрібен код, що читає обидві таблиці, і час на звірку; перемикання застосунків узгоджується |
| Планове вікно обслуговування | Мала або середня таблиця, є узгоджений час простою | Запис зупиняється, частина запитів отримує помилку, потрібен підготовлений знімок для відкату |
Практичне правило: до кількох мільйонів рядків і помірного запису — онлайн-спосіб; глибока зміна структури — перенесення на нову таблицю з подальшою звіркою; невеликі таблиці дешевше й передбачуваніше перебудувати в планове вікно, коли запис зупиняється на хвилини.
Етапи робіт: від аудиту навантаження до передачі бази
Порядок робіт будують від навантаження, а не від зручності вікна: поки таблиця відкрита на запис, зміна конкурує за блокування, місце та пропускну здатність реплік. Кожен етап закінчується перевірюваним результатом, тому рішення йти далі ухвалюють за цифрами, а не за відчуттям.
- Аудит навантаження на базу. Знімаємо профіль за кілька діб: пікові години, частка операцій запису, найважчі запити, відставання реплік, розмір і швидкість зростання цільових таблиць. На виході — вікно, у якому втручання безпечне.
- Схема проведення робіт. Визначаємо, яка зміна потрібна, чи таблиця перезбирається повністю, чи змінюється на місці, чи вистачить місця на диску, як поводитимуться зовнішні ключі та тригери. Тут же з’являється оцінка тривалості.
- Налаштування міграції. Інструмент pt-online-schema-change переносить дані порціями, тому задаємо розмір порції, допустиме відставання реплік, поріг аварійної зупинки та контроль блокувань. Неправильне налаштування гальмує базу сильніше за саму зміну.
- Пробний прогін. Прогонимо на копії бойової бази з реальним обсягом: заміряємо час, поведінку тригерів, вплив на репліки. Це дає фактичні цифри замість розрахунків.
- Точка відкату. Фіксуємо спосіб і час повернення: вихідна таблиця залишається недоторканою, знімок зроблено, повернення вписується у вікно. Відкат перевіряємо до бойового запуску, а не після.
- Звірка цілісності даних. Порівнюємо кількість рядків і контрольні суми до та після, перевіряємо індекси та зовнішні ключі. Нова схема входить у роботу лише за повного збігу.
- Передача бази. Віддаємо параметри, схему, регламент повторних змін і пороги спостереження, за якими черговий побачить проблему раніше за користувачів.
Опишіть вашу базу й задачу — повернемося з оцінкою та планом за цими етапами.
Що залишається в команди: склад постачання і документація
Робота закінчується не в момент успішної міграції, а коли команда замовника може повторити її без нас.
Тому до постачання входять не тільки сам прогін, а й конфігурації, схеми зв’язків між таблицями та регламенти — те, за чим наступний інженер пройде той самий шлях і отримає той самий результат.
- Робочі конфігурації: параметри копіювання даних, пороги допустимого навантаження на сервер, ліміти очікування блокувань і список таблиць-винятків — як файли поряд із міграціями в проєкті.
- Схеми залежностей таблиць: які зовнішні ключі, тригери та зв’язки «батько — нащадок» впливають на порядок робіт, що переносити першим, а що чекати до останнього.
- Правила доступу: окремий обліковий запис із мінімально достатніми правами, що саме потрібно для створення тригерів і перемикання, а що залишається недоступним за замовчуванням.
- Регламент повторних робіт: покроковий порядок для наступної міграції — від оцінки розміру таблиці та вікна робіт до перевірки реплікації й видалення службових об’єктів.
- Документація щодо відкату: як повернути попередню схему, якщо перемикання не пройшло, які об’єкти видалити і за який строк стан повертається до вихідного.
- Звіт про прогін: час обробки кожної таблиці, затримка реплікації, кількість повторних спроб і точки, де знадобилося втручання інженера.
- Скрипти перевірки: звірка числа рядків і контрольних сум до та після, щоб результат підтверджувався даними, а не словами.
Кейс: переведення великої таблиці на нову структуру без простою
Вузьке місце: перебудова під блокуванням
Таблиця на 180 млн рядків приймала кілька тисяч операцій за секунду, і звичайна зміна типу ключового поля з перебудовою індексів тримала її під блокуванням цілком.
Найближче вікно давало близько 40 хвилин недоступності на запис, суміжним командам довелося б зупиняти фонові завдання, а частина запитів усе одно відвалювалася за тайм-аутом — близько 0,3% операцій губилося й розбиралося вручну.
Як минуло і чим закінчилося
Використали pt-online-schema-change з Percona Toolkit: інструмент заводить тіньову копію таблиці, навішує тригери на зміни та переносить рядки порціями, а при зростанні затримки реплікації сам знижує темп.
Копіювання йшло паралельно з робочим трафіком, без вікна простою — вечірній пік минув без деградації, а перемикання на нову структуру зайняло частки секунди, блокування лише на підміну таблиці.
Після переходу звірили контрольні суми за всіма перенесеними порціями: розбіжностей нуль, повернення до вихідної таблиці залишалося доступним до кінця звірки.
| Метрика | До | Після |
|---|---|---|
| Недоступність на запис | ~40 хвилин | частки секунди |
| Втрачені операції | ~0,3% | 0 |
| Звірка даних | вибіркова, вручну | контрольні суми за всіма порціями |
| Поведінка на піку | зупинка фонових завдань | міграція сама знижувала темп |
| Відкат | відновлення з копії | повернення до вихідної таблиці |
Що робити, якщо в MySQL уже є репліки й тригери?
Уже розгорнутий контур із репліками міграції не заважає, але змінює порядок робіт.
Інструмент створює копію таблиці з новою структурою, наповнює її порціями та синхронізує правки тригерами, а в кінці підміняє вихідну атомарним перейменуванням — репліки отримують ту саму послідовність із журналу.
Свої тригери — перша загвоздка: за замовчуванням інструмент зупиняється, якщо на таблиці вже є тригери, щоб не зламати чужу логіку.
Ключ --preserve-triggers переносить їхні тіла на нову таблицю, але перевірте, що вони не посилаються на старе ім’я явно — після підміни такі посилання стануть битими.
Зовнішні ключі задають ціну та вікно ризику. Режим rebuild_constraints перезбирає дочірні обмеження — довше, зате без проміжку, коли посилання висять на зниклій таблиці; drop_swap швидший, але таке вікно створює, а на зв’язках із каскадним видаленням потребує окремої перевірки. Коли ключі дивляться і всередину, і назовні, зміну проганяють на копії контуру цілком.
Окремий ризик — фільтри реплікації: якщо службова таблиця-копія під них потрапляє, на репліці її не буде, підміна пройде «успішно», а структури роз’їдуться, тому конфігурацію звіряють до старту, а поріг --max-lag призупиняє копіювання при сильному відставанні.
Поки зміна структури не дійшла до всіх реплік, застосунок не повинен читати нові колонки — на відстаючій їх ще немає, звідси відкладене читання старих даних і помилки. Працюємо однією зміною за прохід: прогін, підміна, звірка структури на майстрі й кожній репліці, потім наступна.
Технічні сумніви: питання, які ставлять перед стартом
Перед перебудовою великої таблиці на бойовій базі спливає один і той самий набір питань: скільки дістанеться живому навантаженню, що буде при обриві, як поводитимуться зовнішні ключі та тригери, чим підтверджується результат. Нижче — відповіді, які зазвичай потрібні до узгодження вікна.
Перебудова таблиці покладе базу?
Копіювання йде порціями з паузами між ними. Задаються пороги за кількістю активних запитів і відставанням репліки: при перевищенні копіювання зупиняється й чекає, поки база звільниться. Прод отримує добавку до навантаження, а не просідання за часом відповіді.
Що буде, якщо роботу перервати?
У Percona Toolkit при зупинці або помилці інструмент прибирає свої тригери та тимчасову таблицю, вихідна залишається недоторканою, продовжити можна з точки зупинки. Необоротним є лише фінальне перемикання таблиць — його тримають коротким і роблять у узгодженому вікні.
Зовнішні ключі та тригери — що з ними?
Дочірні таблиці перемикаються окремим кроком, інакше зовнішні ключі продовжать дивитися на стару. Тригери, що висіли на вихідній таблиці, під час копіювання не спрацьовують — їхню логіку переносять заздалегідь, інакше частина змін губиться.
Як переконатися, що дані не загубилися?
Після перемикання звіряємо число рядків і контрольні суми за діапазонами, окремо — записи, змінені під час копіювання. Розбіжності розбираємо до видалення тимчасової таблиці: поки вона на місці, відкат ще можливий.
А якщо копій бази кілька?
Репліки не успадковують перебудову — схему на кожній копії приводять своїм проходом. Або повторюємо міграцію на кожній, або перезбираємо копію з резервної та наздоганяємо її журналом змін, якщо відставання допустиме.
Обговоримо задачу: надішлемо план робіт та оцінку
Щоб повернутися з планом етапів робіт та оцінкою термінів, нам потрібні ввідні щодо вашої бази — не абстрактне «є сервер з MySQL», а конкретика: цільові таблиці та їхній обсяг, движок зберігання, наявність зовнішніх ключів, тригерів і представлень, топологія реплікації, вікно низького навантаження.
Чим точніші вихідні дані, тим менше сюрпризів на бойовому контурі: за ними заздалегідь видно, де знадобиться перезбирання таблиці, а де достатньо перемикання через перейменування.
Що ви отримуєте після розбору задачі:
- План етапів робіт із порядком дій: підготовка, пробний прогін на копії, міграція, перевірка цілісності даних, фіксація точки відкату.
- Оцінку термінів із розбивкою за етапами та позначкою, де потрібне вікно узгодження з бізнесом.
- Схему відкату: які метадані зберігаємо і як повернутися до вихідної таблиці, якщо перевірки не пройшли.
- Перелік ризиків під вашу конфігурацію: тривалі блокування, зростання навантаження на репліки, відставання підлеглих вузлів.
- Набір метрик супроводу: затримка реплікації, кількість активних з’єднань, швидкість обробки рядків, що копіюються.
- Чернетку регламенту для чергової зміни: що робити при спрацюванні сигналів і коли зупиняти перенесення.
Перевірку проводимо на вашому контурі — на копії бойової бази або стенді тієї самої конфігурації, щоб результат прогону переносився далі без припущень і перерахунків.
Опишіть задачу: які таблиці чіпаємо, яке навантаження в години пік, чи є вікно для перемикання. Повернемося з планом етапів та оцінкою термінів.







