Транзакційний DDL робочий процес для MySQL


25

Я був трохи здивований, виявивши , що заяви DDL ( alter table, і create indexт.д.) неявно зробити поточну транзакцію в MySQL. Починаючи з MS SQL Server, можливість змінювати базу даних в транзакції локально (потім відкотився) була важливою частиною мого робочого процесу. Для безперервної інтеграції відкат використовувався, якщо міграція з будь-якої причини спричинялася, так що принаймні ми не залишали базу даних у напівміграційному стані.

Як люди вирішують ці дві проблеми при використанні MySQL з міграціями та постійною інтеграцією?


Хрест розміщено від SO. stackoverflow.com/q/28197013/614523 Там не дуже сподобався.
сеннетт

1
Для постійної інтеграції розгляньте знімки LVM як спосіб дуже швидкого створення цілого середовища, яке знаходиться у відомому стані.
Рік Джеймс

5
Ви завжди можете оновити до Postgres - він підтримує транзакційний DDL (SCNR).
a_horse_with_no_name

3
Я погоджуюся з @a_horse_with_no_name, якщо це ваш робочий процес, серйозно подумайте про використання PosgreSQL, який має транзакційний DDL разом з багатьма іншими приємними функціями.
Ренцо

Відповіді:


9

Для багатьох людей п'ята ахіллеса MySQL - це неявна фіксація.

Відповідно до пункту 3 книги

Посібник з вивчення сертифікації MySQL 5.0

наступні команди можуть і порушують транзакцію

  • ALTER TABLE
  • BEGIN
  • CREATE INDEX
  • DROP DATABASE
  • DROP INDEX
  • DROP TABLE
  • RENAME TABLE
  • TRUNCATE TABLE
  • LOCK TABLES
  • UNLOCK TABLES
  • SET AUTOCOMMIT = 1
  • START TRANSACTION

ПРОПОЗИЦІЯ

Якщо мова йде про MySQL, будь-які створені вами завдання ContinuousIntegration (CI) / SelfService завжди повинні робити завдання Transaction та сценарії DDL взаємно виключними.

Це дає можливість створити парадигми, які б це зробили

  • підтримка транзакцій, які належним чином ізольовані START TRANSACTION/COMMITблоками
  • керування DDL шляхом скриптування DDL самостійно, запуск такого DDL, як конструктор чи деструктор
    • Конструктор: DDL для створення таблиць з новим дизайном
    • Destructor: DDL для повернення таблиць назад до попереднього дизайну
  • ніколи не поєднуйте ці операції під одним завданням

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

ЧОМУ НЕ ЛВМ?

Знімки LVM є чудовими, і відновлення цілих примірників баз даних без необхідності виконувати важку обробку SQL є ідеальним. Однак, якщо мова йде про MySQL, вам доведеться враховувати два двигуни зберігання даних: InnoDB і MyISAM.

База даних All-InnoDB

Подивіться на архітектуру InnoDB (малюнок люб’язно наданий КТ Percona Вадиму Ткаченку)

InnoDB сантехніка

InnoDB має багато рухомих частин

  • Простір системних таблиць
    • Словник даних
    • Подвійний буфер запису (послідовність підтримки даних; використовується для відновлення аварійних ситуацій)
    • Вставити буфер (зміни буфера для вторинних унікальних індексів)
    • Відхилення сегментів
    • Скасувати пробіл (де може статися найконтрольованіше зростання)
  • Буферний басейн InnoDB
    • Брудні сторінки даних
    • Брудні покажчики
    • Зміни до індексів UnUnique
  • Інші важливі кеші пам'яті

Зйомка LVM бази даних All-InnoDB із невмілими змінами, що плавають у кешах пулу та пам'яті, дасть набір даних, що потребує відновлення аварії InnoDB після відновлення LUN та запуску mysqld.

ПЕРЕВАГА ДЛЯ ALL-InnoDB

Якщо ви можете вимкнути MySQL перед тим, як зробити знімок

    1. Біжи SET GLOBAL innodb_fast_shutdown = 0;
    1. Біжи SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Біжи SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Повторіть крок 3, поки Innodb_buffer_pool_pages_dirty не дорівнює 0 або максимально наблизиться до 0.
    1. service mysql stop
    1. Зробіть знімок LVM
    1. service mysql stop

Якщо ви не можете відключити, але зробити знімок із MySQL Live

    1. Біжи SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Біжи SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Повторіть крок 2, поки Innodb_buffer_pool_pages_dirty не дорівнює 0 або максимально наблизиться до 0.
    1. Зробіть знімок LVM
    1. Біжи SET GLOBAL innodb_max_dirty_pages_pct = 75;

База даних All-MyISAM або суміш InnoDB / MyISAM

При зверненні MyISAM підтримує кількість відкритих файлів для обробки. Якщо MySQL виходить з ладу, будь-яка таблиця MyISAM з числом відкритих файлів кількість файлів> 0 буде позначена як збій і потребує ремонту (навіть якщо з даними нічого не буває).

Зйомка LVM бази даних, яка використовує таблиці MyISAM, матиме одну чи більше таблиць MyISAM, які потребують ремонту, коли знімок буде відновлено та запущено mysqld.

ПЕРЕВАГА ДЛЯ All-MyISAM або InnoDB / MyISAM Mix

Якщо ви можете вимкнути MySQL перед тим, як зробити знімок

    1. Біжи SET GLOBAL innodb_fast_shutdown = 0;
    1. Біжи SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Біжи SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Повторіть крок 3, поки Innodb_buffer_pool_pages_dirty не дорівнює 0 або максимально наблизиться до 0.
    1. service mysql stop
    1. Зробіть знімок LVM
    1. service mysql stop

Якщо ви не можете відключити, але зробити знімок із MySQL Live

Ви можете застосувати прошивання певних таблиць InnoDB

    1. Біжи SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Біжи SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Повторіть крок 2, поки Innodb_buffer_pool_pages_dirty не дорівнює 0 або максимально наблизиться до 0.
    1. Запуск FLUSH TABLES innodb_tbl1,... FOR EXPORT;на критичних таблицях InnoDB
    1. Біжи FLUSH TABLES WITH READ LOCK;
    1. Зробіть знімок LVM
    1. Біжи UNLOCK TABLES;
    1. Біжи SET GLOBAL innodb_max_dirty_pages_pct = 75;

Чи може допомогти реплікація MySQL?

У той час як ви можете відновити один знімок LVM на двох серверах і встановити MySQL Master / Slave Replication, це стає додатковим джерелом очищення будинку при відновленні знімків.

Якщо ви запускаєте завдання CI на Master і ці завдання невеликі, тиражування може бути певним часом за певних обставин. Ви можете просто бігти STOP SLAVE;на Рабі, запускати завдання CI на Майстрі та бігати START SLAVE;на Рабі, коли дані Магістра підтверджуються.

Якщо завдання CI попереджають занадто багато даних, ви можете відновити знімок LVM та налаштування реплікації з нуля. Якщо ви часто виявляєте, що це робите часто, ви, можливо, могли б зробити це з налаштуванням MySQL Replication.

ЗАКЛЮЧНІ МИСЛИ

  • Найкраще використовувати декілька серверів БД (3 або більше) для проведення тестів на відновлення та регресію.
  • Перетворіть залишилися таблиці MyISAM в InnoDB, якщо ці таблиці не повинні залишатися MyISAM.
  • Якщо вміст ваших даних є чутливим, вам слід виконати завдання CI для очищення даних після відновлення знімка перед початком будь-яких тестів. В якості альтернативи ви можете зробити знімки MySQL з уже прочищеними даними.

4

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

У процесі розгортання виробництва ви зазвичай проходите через розробку, QA або навіть передвиробниче середовище, щоб перевірити свої зміни, так само як і для будь-яких змін коду.

Зауважте, що це не специфічно для MySQL: бази даних Oracle також неявно робитимуть COMMIT під час видачі «змінити таблицю» тощо.

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

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