Transakcyjny przepływ pracy DDL dla MySQL

25

Byłem trochę zaskoczony, aby odkryć, że DDL ( alter table, create indexetc) niejawnie popełnić bieżącej transakcji w MySQL. Począwszy od MS SQL Server, możliwość dokonywania lokalnych zmian bazy danych w transakcji (która została następnie wycofana) była ważną częścią mojego przepływu pracy. W celu ciągłej integracji zastosowano wycofanie, jeśli migracja nastąpiła z jakiegokolwiek powodu, dlatego przynajmniej nie pozostawiliśmy bazy danych w stanie częściowo migrowanym.

Jak ludzie rozwiązują te dwa problemy, używając MySQL do migracji i ciągłej integracji?

sennett
źródło
Krzyż wysłany z SO. stackoverflow.com/q/28197013/614523 Nie zyskałem tam wiele miłości.
sennett
1
W przypadku ciągłej integracji rozważ migawki LVM jako sposób na bardzo szybkie utworzenie całego środowiska, które jest w znanym stanie.
Rick James
5
Zawsze możesz uaktualnić do Postgres - obsługuje transakcyjny DDL (SCNR).
a_horse_w_no_name
3
Zgadzam się z @a_horse_with_no_name, jeśli jest to twój przepływ pracy, poważnie rozważ użycie PosgreSQL, który ma transakcyjny DDL wraz z wieloma innymi fajnymi funkcjami.
Renzo

Odpowiedzi:

9

Dla wielu osób piętą achillesową MySQL jest niejawne zatwierdzenie.

Zgodnie z § 4 książki

Przewodnik po certyfikacji MySQL 5.0

następujące polecenia mogą i spowodują zerwanie transakcji

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

SUGESTIA

Jeśli chodzi o MySQL, wszelkie tworzone przez ciebie zadania ContinuousIntegration (CI) / SelfService powinny zawsze wykluczać wzajemnie wykluczające się zadania transakcyjne i skrypty DDL.

Daje to możliwość stworzenia paradygmatów, które by to zrobiły

  • obsługują transakcje, które są odpowiednio izolowane za pomocą START TRANSACTION/COMMITbloków
  • kontrola nad DDL poprzez samodzielne skryptowanie DDL, uruchamianie takiego DDL jako konstruktora lub destruktora
    • Konstruktor: DDL do tworzenia tabel o nowym projekcie
    • Destructor: DDL, aby przywrócić tabele do poprzedniego projektu
  • nigdy nie łącz tych operacji w ramach jednego zadania

OSTRZEŻENIE: Jeśli używasz do tego MyISAM, możesz (nie) uprzejmie dodać MyISAM do listy rzeczy, które mogą przerwać transakcję, być może nie pod względem domniemanego zatwierdzenia, ale zdecydowanie pod względem spójności danych, gdyby kiedykolwiek wycofanie potrzebne.

DLACZEGO NIE LVM?

Migawki LVM są świetne, a przywracanie całych instancji baz danych bez konieczności wykonywania intensywnego przetwarzania SQL jest idealne. Jednak jeśli chodzi o MySQL, musisz wziąć pod uwagę dwa silniki pamięci: InnoDB i MyISAM.

Baza danych All-InnoDB

Spójrz na architekturę InnoDB (Zdjęcie dzięki uprzejmości Percona CTO Vadim Tkachenko)

InnoDB Hydraulika

InnoDB ma wiele ruchomych części

  • Systemowa przestrzeń tabel
    • Słownik danych
    • Podwójny bufor zapisu (spójność danych pomocniczych; używany do odzyskiwania po awarii)
    • Wstaw bufor (zmiany buforów na wtórne nieunikalne indeksy)
    • Wycofywanie segmentów
    • Cofnij przestrzeń (gdzie może nastąpić najbardziej niekontrolowany wzrost)
  • Pula buforów InnoDB
    • Brudne strony danych
    • Brudne strony indeksu
    • Zmiany w indeksach NonUnique
  • Inne ważne pamięci podręczne

Wykonanie migawki LVM dla bazy danych All-InnoDB z niezatwierdzonymi zmianami pływającymi w puli buforów i pamięciach podręcznych dałoby zestaw danych, który wymagałby odzyskiwania po awarii InnoDB po przywróceniu LUN i uruchomieniu mysqld.

SUGESTIA DLA WSZYSTKICH InnoDB

Jeśli możesz zamknąć MySQL przed zrobieniem migawki

    1. Biegać SET GLOBAL innodb_fast_shutdown = 0;
    1. Biegać SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Biegać SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Powtarzaj krok 3, aż Innodb_buffer_pool_pages_dirty wyniesie 0 lub będzie możliwie jak najbliżej 0
    1. service mysql stop
    1. Wykonaj migawkę LVM
    1. service mysql stop

Jeśli nie możesz zamknąć systemu, ale zrób migawkę za pomocą MySQL Live

    1. Biegać SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Biegać SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Powtarzaj krok 2, aż Innodb_buffer_pool_pages_dirty wyniesie 0 lub będzie możliwie jak najbliżej 0
    1. Wykonaj migawkę LVM
    1. Biegać SET GLOBAL innodb_max_dirty_pages_pct = 75;

Baza danych All-MyISAM lub InnoDB / MyISAM Mix

Po uzyskaniu dostępu do MyISAM zachowuje liczbę otwartych uchwytów plików. Jeśli MySQL ulegnie awarii, każda tabela MyISAM z liczbą uchwytów otwartego pliku> 0 zostanie oznaczona jako awaria i wymaga naprawy (nawet jeśli nic nie jest nie tak z danymi).

Wykonanie migawki LVM dla bazy danych, w której są używane tabele MyISAM, będzie wymagało naprawy jednej lub wielu tabel MyISAM po przywróceniu migawki i uruchomieniu mysqld.

PROPOZYCJA DLA All-MyISAM lub InnoDB / MyISAM Mix

Jeśli możesz zamknąć MySQL przed zrobieniem migawki

    1. Biegać SET GLOBAL innodb_fast_shutdown = 0;
    1. Biegać SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Biegać SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Powtarzaj krok 3, aż Innodb_buffer_pool_pages_dirty wyniesie 0 lub będzie możliwie jak najbliżej 0
    1. service mysql stop
    1. Wykonaj migawkę LVM
    1. service mysql stop

Jeśli nie możesz zamknąć systemu, ale zrób migawkę za pomocą MySQL Live

Możesz wymusić opróżnianie niektórych tabel InnoDB

    1. Biegać SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Biegać SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Powtarzaj krok 2, aż Innodb_buffer_pool_pages_dirty wyniesie 0 lub będzie możliwie jak najbliżej 0
    1. Uruchom FLUSH TABLES innodb_tbl1,... FOR EXPORT;na krytycznych tabelach InnoDB
    1. Biegać FLUSH TABLES WITH READ LOCK;
    1. Wykonaj migawkę LVM
    1. Biegać UNLOCK TABLES;
    1. Biegać SET GLOBAL innodb_max_dirty_pages_pct = 75;

Czy replikacja MySQL może pomóc?

Chociaż można przywrócić jedną migawkę LVM na dwóch serwerach i skonfigurować replikację MySQL Master / Slave, staje się ona dodatkowym źródłem czyszczenia domu podczas przywracania migawek.

Jeśli uruchamiasz zadania CI na Master, a te zadania są małe, replikacja może w pewnych okolicznościach zaoszczędzić czas. Możesz po prostu uruchomić STOP SLAVE;Slave, uruchomić zadania CI na Master i uruchomić START SLAVE;Slave, gdy dane Master będą certyfikowane.

Jeśli zadania CI ostrzegają o zbyt dużej ilości danych, możesz przywrócić migawkę LVM i replikację konfiguracji od zera. Jeśli często to robisz, prawdopodobnie możesz zrobić to z konfiguracją replikacji MySQL.

KOŃCOWE PRZEMYŚLENIA

  • Najlepiej jest używać wielu serwerów DB (3 lub więcej) do wykonywania testów przywracania i regresji.
  • Konwertuj pozostałe tabele MyISAM na InnoDB, jeśli tabele te nie muszą pozostać MyISAM.
  • Jeśli zawartość danych jest wrażliwa, należy wykonać zadanie CI w celu wyczyszczenia danych po przywróceniu migawki przed rozpoczęciem jakichkolwiek testów. Alternatywnie możesz chcieć zrobić migawki MySQL z już wyczyszczonymi danymi.
RolandoMySQLDBA
źródło
4

Jeśli mówisz o ciągłej integracji, to zakładam, że jest to środowisko programistyczne. W takim przypadku powiedziałbym, że osoba dokonująca zmian strukturalnych musi je przetestować, aby upewnić się, że nie psują rzeczy innym, podobnie jak ktoś aktualizujący wspólną bibliotekę: Testuj we własnym piaskownicy przed zatwierdzeniem takich zmian.

W procesie wdrażania produkcyjnego zwykle testujesz zmiany w środowisku deweloperskim, kontroli jakości, a nawet przedprodukcyjnym, tak samo jak w przypadku zmian w kodzie.

Zauważ, że nie jest to specyficzne dla MySQL: bazy danych Oracle również domyślnie wykonałyby COMMIT podczas wydawania „alter table” itp.

Teraz, jeśli chcesz się zabezpieczyć, możesz oczywiście wcześniej wykonać kopię zapasową lub LVM lub migawkę systemu plików, jeśli Twój system to potrafi. Możesz także mieć niewolnika, który możesz opóźnić / zatrzymać jako zabezpieczenie przed wrażliwymi operacjami.

phil_w
źródło