Преди да се опитате да извършите каквито и да е промени в схемата на вашите производствени бази данни, трябва да се уверите, че имате стабилен план за връщане назад; и че вашата процедура за промяна е била успешно тествана и валидирана в отделна среда. В същото време ваша отговорност е да се уверите, че промяната не причинява никакво или най-малкото възможно въздействие, приемливо за бизнеса. Определено не е лесна задача.
В тази статия ще разгледаме как да извършваме промени в базата данни на MySQL и MariaDB по контролиран начин. Ще говорим за някои добри навици в ежедневната ви работа с DBA. Ще се съсредоточим върху предварителни изисквания и задачи по време на действителните операции и проблеми, с които може да се сблъскате, когато се занимавате с промени в схемата на базата данни. Ще говорим и за инструменти с отворен код, които могат да ви помогнат в процеса.
Сценарии за тестване и връщане назад
Резервно копие
Има много начини да загубите данните си. Неуспехът при надграждане на схемата е един от тях. За разлика от кода на приложението, не можете да пуснете пакет файлове и да декларирате, че нова версия е била успешно внедрена. Също така не можете просто да върнете по-стар набор от файлове, за да върнете промените си обратно. Разбира се, можете да изпълните друг SQL скрипт, за да промените базата данни отново, но има случаи, когато единственият точен начин за връщане на промените е чрез възстановяване на цялата база данни от архивиране.
Но какво ще стане, ако не можете да си позволите да върнете базата данни до последното архивиране или прозорецът ви за поддръжка не е достатъчно голям (като се има предвид производителността на системата), така че не можете да извършите пълно архивиране на базата данни преди промяната?
Човек може да има усъвършенствана, излишна среда, но докато данните се модифицират както на първични, така и на резервни места, няма какво да се направи по въпроса. Много скриптове могат да се изпълняват само веднъж или промените са невъзможни за отмяна. Повечето от кода за промяна на SQL попадат в две групи:
- Изпълнете веднъж – не можете да добавите една и съща колона към таблицата два пъти.
- Невъзможно е да се отмени – след като изпуснете тази колона, тя е изчезнала. Несъмнено бихте могли да възстановите базата си данни, но това не е точно отмяна.
Можете да се справите с този проблем по поне два възможни начина. Единият би бил да активирате двоичния дневник и да направите резервно копие, което е съвместимо с PITR. Такова архивиране трябва да бъде пълно, пълно и последователно. За xtrabackup, стига да съдържа пълен набор от данни, той ще бъде PITR-съвместим. За mysqldump има опция да го направите и PITR-съвместим. За по-малки промени, вариант на архивиране на mysqldump би бил да вземе само подмножество от данни за промяна. Това може да стане с опцията --where. Архивът трябва да бъде част от планираната поддръжка.
mysqldump -u -p --lock-all-tables --where="WHERE employee_id=100" mydb employees> backup_table_tmp_change_07132018.sql
Друга възможност е да използвате CREATE TABLE AS SELECT.
Можете да съхранявате данни или прости промени в структурата под формата на фиксирана временна таблица. С този подход ще получите източник, ако трябва да върнете промените си назад. Може да е доста удобно, ако не променяте много данни. Отмяната може да се извърши, като се извадят данни от него. Ако възникнат грешки при копирането на данните в таблицата, те автоматично се отхвърлят и не се създават, така че се уверете, че изявлението ви създава копие, от което се нуждаете.
Очевидно има и някои ограничения.
Тъй като подреждането на редовете в основните оператори SELECT не винаги може да бъде определено, CREATE TABLE ... IGNORE SELECT и CREATE TABLE ... REPLACE SELECT са маркирани като опасни за репликация, базирана на изрази. Такива изрази произвеждат предупреждение в регистъра за грешки, когато се използва режим, базиран на изрази, и се записват в двоичния дневник, като се използва формат, базиран на редове, когато се използва СМЕСЕН режим.
Много прост пример за такъв метод може да бъде:
CREATE TABLE tmp_employees_change_07132018 AS SELECT * FROM employees where employee_id=100;
UPDATE employees SET salary=120000 WHERE employee_id=100;
COMMMIT;
Друга интересна опция може да бъде базата данни за ретроспекция на MariaDB. Когато се случи грешна актуализация или изтриване и искате да се върнете към състояние на базата данни (или просто таблица) в определен момент от време, можете да използвате функцията за ретроспекция.
Обратно връщане в даден момент позволява на DBA да възстановяват данните по-бързо чрез връщане на транзакциите към предишен момент във времето, вместо да извършват възстановяване от резервно копие. Въз основа на DML събития, базирани на ROW, ретроспекцията може да трансформира двоичния дневник и да обърне целите. Това означава, че може да помогне за бързо отмяна на дадени промени в редовете. Например, той може да промени събитията DELETE на INSERT и обратно, и ще разменя WHERE и SET части от събитията UPDATE. Тази проста идея може драстично да ускори възстановяването от определени видове грешки или бедствия. За тези, които са запознати с базата данни на Oracle, това е добре позната функция. Ограничението на ретроспекцията на MariaDB е липсата на поддръжка на DDL.
Създайте подчинен за отложена репликация
От версия 5.6 MySQL поддържа отложена репликация. Подчинен сървър може да изостава от главния поне за определено време. Закъснението по подразбиране е 0 секунди. Използвайте опцията MASTER_DELAY за CHANGE MASTER TO, за да зададете забавянето на N секунди:
CHANGE MASTER TO MASTER_DELAY = N;
Би било добър вариант, ако нямате време да подготвите подходящ сценарий за възстановяване. Трябва да имате достатъчно забавяне, за да забележите проблемната промяна. Предимството на този подход е, че не е необходимо да възстановявате вашата база данни, за да извадите данни, необходими за коригиране на вашата промяна. Резервната база данни е готова и работи, готова за събиране на данни, което минимизира необходимото време.
Създайте асинхронно подчинено устройство, което не е част от клъстера
Когато става въпрос за клъстер Galera, тестването на промените не е лесно. Всички възли работят с едни и същи данни и голямото натоварване може да навреди на контрола на потока. Така че не само трябва да проверите дали промените са приложени успешно, но и какво е било въздействието върху състоянието на клъстера. За да направите вашата тестова процедура възможно най-близо до производственото натоварване, може да искате да добавите асинхронен подчинен към вашия клъстер и да стартирате своя тест там. Тестът няма да повлияе на синхронизацията между възлите на клъстера, защото технически не е част от клъстера, но ще имате възможност да го проверите с реални данни. Такъв подчинен може лесно да се добави от ClusterControl.
ClusterControl добавяне на асинхронен подчиненКакто е показано на горната екранна снимка, ClusterControl може да автоматизира процеса на добавяне на асинхронен подчинен по няколко начина. Можете да добавите възела към клъстера, да забавите подчинения. За да намалите въздействието върху главния, можете да използвате съществуващо резервно копие вместо главното като източник на данни при изграждането на подчинения.
Клониране на база данни и измерване на времето
Добрият тест трябва да бъде възможно най-близък до промяната в производството. Най-добрият начин да направите това е да клонирате съществуващата си среда.
ClusterControl Clone Cluster за тестИзвършване на промени чрез репликация
За да имате по-добър контрол върху промените си, можете да ги приложите на подчинен сървър предварително и след това да извършите превключването. За репликация, базирана на изрази, това работи добре, но за репликация, базирана на ред, това може да работи до известна степен. Репликацията, базирана на редове, позволява да съществуват допълнителни колони в края на таблицата, така че стига да може да записва първите колони, ще бъде добре. Първо приложете тези настройки към всички подчинени устройства, след това преминете към един от подчинените и след това приложете промяната към главния и го прикрепете като подчинен. Ако вашата модификация включва вмъкване или премахване на колона в средата на таблицата, тя ще работи с репликация, базирана на редове.
Операция
По време на прозореца за поддръжка не искаме да имаме трафик на приложения в базата данни. Понякога е трудно да се изключат всички приложения, разпространени в цялата компания. Като алтернатива искаме да позволим само на някои специфични хостове да имат достъп до MySQL от разстояние (например системата за наблюдение или резервния сървър). За тази цел можем да използваме филтрирането на пакети в Linux. За да видим какви правила за филтриране на пакети са налични, можем да изпълним следната команда:
iptables -L INPUT -v
За да затворим MySQL порта на всички интерфейси, които използваме:
iptables -A INPUT -p tcp --dport mysql -j DROP
и за да отворите отново MySQL порта след прозореца за поддръжка:
iptables -D INPUT -p tcp --dport mysql -j DROP
За тези, които нямат root достъп, можете да промените max_connection на 1 или „пропуснете работа в мрежа“.
Регистриране
За да стартирате процеса на регистриране, използвайте командата tee в подканата на MySQL клиента, както следва:
mysql> tee /tmp/my.out;
Тази команда казва на MySQL да регистрира както входа, така и изхода на текущата ви сесия за влизане в MySQL във файл с име /tmp/my.out . След това изпълнете вашия скриптов файл с командата източник.
За да получите по-добра представа за времето си за изпълнение, можете да го комбинирате с функцията за профилиране. Стартирайте профайлъра с
SET profiling = 1;
След това изпълнете своята заявка с
SHOW PROFILES;
виждате списък със заявки, за които профайлърът има статистика. И накрая, вие избирате с коя заявка да разгледате
SHOW PROFILE FOR QUERY 1;
Инструменти за мигриране на схеми
Много пъти направо ALTER на главния не е възможен - в повечето случаи причинява забавяне на подчинения и това може да не е приемливо за приложенията. Това, което може да се направи обаче, е промяната да се извърши в подвижен режим. Можете да започнете с подчинени и след като промяната бъде приложена към подчинения, да мигрирате един от подчинените като нов главен, да понижите стария главен до подчинен и да изпълните промяната върху него.
Инструмент, който може да помогне с такава задача, е промяната на pt-online-schema-change на Percona. Pt-online-schema-change е ясна - създава временна таблица с желаната нова схема (например, ако сме добавили индекс или премахнахме колона от таблица). След това създава тригери на старата таблица. Тези тригери са там, за да отразяват промените, които се случват на оригиналната маса, към новата таблица. Промените се отразяват по време на процеса на промяна на схемата. Ако към оригиналната таблица се добави ред, той също се добавя към новата. Той емулира начина, по който MySQL променя вътрешно таблиците, но работи върху копие на таблицата, която искате да промените. Това означава, че оригиналната таблица не е заключена и клиентите могат да продължат да четат и променят данни в нея.
По същия начин, ако ред е променен или изтрит в старата таблица, той също се прилага в новата таблица. След това започва фонов процес на копиране на данни (използвайки LOW_PRIORITY INSERT) между старата и новата таблица. След като данните бъдат копирани, се изпълнява RENAME TABLE.
Друг интересен инструмент е gh-ost. Gh-ost създава временна таблица с променената схема, точно както прави pt-online-schema-change. Той изпълнява INSERT заявки, които използват следния модел за копиране на данни от стара в нова таблица. Въпреки това не използва тригери. За съжаление тригерите могат да бъдат източник на много ограничения. gh-ost използва двоичния лог поток за улавяне на промените в таблицата и асинхронно ги прилага към таблицата ghost. След като потвърдихме, че gh-ost може да изпълни правилно промяната на нашата схема, е време всъщност да я изпълним. Имайте предвид, че може да се наложи да махнете ръчно стари таблици, създадени от gh-ost по време на процеса на тестване на миграцията. Можете също да използвате флагове --initially-drop-ghost-table и --initially-drop-old-table, за да помолите gh-ost да го направи вместо вас. Последната команда за изпълнение е точно същата, както използвахме за тестване на нашата промяна, просто добавихме --execute към нея.
pt-online-schema-change и gh-ost са много популярни сред потребителите на Galera. Въпреки това Galera има някои допълнителни опции. Двата метода за пълна изолация на поръчките (TOI) и непрекъснато надграждане на схемата (RSU) имат своите плюсове и минуси.
TOI - Това е методът за репликация на DDL по подразбиране. Възелът, който създава набора за запис, открива DDL по време на синтактичен анализ и изпраща събитие за репликация за SQL израза, преди дори да започне обработката на DDL. Надстройките на схемата се изпълняват на всички възли на клъстер в една и съща обща последователност на поръчките, предотвратявайки извършването на други транзакции по време на операцията. Този метод е добър, когато искате вашите онлайн надстройки на схеми да се репликират през клъстера и нямате нищо против да заключите цялата таблица (подобно на това как промените на схемата по подразбиране са се случили в MySQL).
SET GLOBAL wsrep_OSU_method='TOI';
RSU - извършване на надстройките на схемата локално. При този метод вашите записи засягат само възела, на който се изпълняват. Промените не се репликират в останалата част от клъстера. Този метод е добър за неконфликтни операции и няма да забави клъстера.
SET GLOBAL wsrep_OSU_method='RSU';
Докато възелът обработва надстройката на схемата, той се десинхронизира с клъстера. Когато приключи с обработката на надстройката на схемата, той прилага отложени събития за репликация и се синхронизира с клъстера. Това може да е добър вариант за стартиране на тежки творения на индекси.
Заключение
Представихме тук няколко различни метода, които могат да ви помогнат при планирането на промените на вашата схема. Разбира се, всичко зависи от вашето приложение и бизнес изисквания. Можете да създадете своя план за промяна, да извършите необходимите тестове, но все още има малък шанс нещо да се обърка. Според закона на Мърфи – „нещата ще се объркат във всяка дадена ситуация, ако им дадете шанс“. Затова се уверете, че изпробвате различни начини за извършване на тези промени и изберете този, който ви е най-удобен.