Имали ли сте бавни времена за стартиране на MySQL в режим GTID? Наскоро се сблъскахме с този проблем при едно от внедряванията на MySQL хостинг и се заехме да разрешим проблема. В този блог ние разбиваме проблема, който може да е забавянето на времето за рестартиране на MySQL, как да отстраните грешки за внедряването си и какво можете да направите, за да намалите началното си време и да подобрите разбирането си за базираното на GTID репликация.
Как открихме проблема
Проучвахме бавни времена за стартиране на MySQL при нисък клас, базиран на диск MySQL 5.7.21 внедряване, което имаше активиран режим на GTID. Системата беше част от двойка главен-подчинен и беше под умерено натоварване при запис. При рестартиране по време на планирана поддръжка забелязахме, че на сървъра на базата данни са необходими 5-10 минути, за да се стартира и да започне да приема връзки. Такова забавяне нямаше смисъл, затова се заехме да разследваме.
Отстраняване на грешки във вашия бавен начален час на MySQL
Използвахме популярния инструмент на Percona pt-ioprofile, за да видим какво прави базата данни. pt-ioprofile е много важна помощна програма в популярния инструментариум на Percona, който се използва за отстраняване на грешки в MySQL проблеми и можете да видите пълния списък с функции в тяхната документация. pt-ioprofile инструментът използва strace и lsof за да гледате I/O на процес и да разпечатате таблица с файлове и I/O активност.
И така, стартирахме MySQL, изчакахме mysqld процес, за да се създаде и стартира pt-ioprofile за да видите какъв може да е проблемът:
# pt-ioprofile --profile-process mysqld --run-time 200 Tue Oct 9 15:42:24 UTC 2018 Tracing process ID 18677 total pread read pwrite write fsync fdatasync open close getdents lseek fcntl filename ... 216.550641 0.000000 216.550565 0.000000 0.000000 0.000000 0.000000 0.000015 0.000040 0.000000 0.000021 0.000000 /mysql_data/binlogs/mysql-bin.000014 ...
Какво забавя рестартирането на MySQL?
При изпълнение на това многократно забелязахме следното:
- mysqld процесът прекарваше по-голямата част от времето си в четене на най-новия двоичен регистрационен файл. Това беше така, дори когато сървърът беше спрян грациозно и нямаше нужда от възстановяване при срив и т.н.
- Сървърът също прекара значително време в зареждане на файловете с данни InnoDB, но това време беше много по-малко в сравнение с времето, прекарано в четене на последния двоичен регистрационен файл.
- Ако сървърът бъде рестартиран веднага, това следващо рестартиране ще бъде много по-бързо.
- Тъй като изключване на базата данни изтрива двоичния дневник и създава нов при стартиране, направихме допълнителен експеримент – преди да изключим сървъра, изчистихме двоичните регистрационни файлове. Следващото стартиране на сървъра отново беше бързо.
Тези наблюдения ясно сочат факта, че MySQL прекарва много време в четене на най-новия двоичен регистрационен файл. Ако файлът беше малък, както би било, когато регистрационният файл е бил прочистен преди изключване, стартирането беше бързо.
Бавно начално време на MySQL в GTID? Размерът на вашия двоичен регистрационен файл може да е проблем. Щракнете за туит
Разбиране на Binlog GTID възстановяване
Както се оказва, за да попълни стойностите на gtid_executed и gtid_purged, MySQL сървърът трябва да анализира двоичните регистрационни файлове.
Ето обобщението на препоръката за метода за документиране на MySQL 5.7, базирана на НЕВЕРНО или ИСТИННО четене:
Когато binlog_gtid_simple_recovery =FALSE:
За да изчислите gtid_executed:
- Повторете двоични регистрационни файлове от най-новите, като спрете на първия файл, който има Previous_gtids_log_event влизане.
- Използване на всички GTID от Previous_gtids_log_event и Gtid_log_events от този двоичен регистрационен файл и съхранявайте този набор GTID вътрешно. Нарича се gtids_in_binlog.
- Стойност на gtid_executed се изчислява като обединение на gtids_in_binlog и GTID в таблицата mysql.gtid_executed .
Този процес може да отнеме много време, ако има голям брой двоични регистрационни файлове без GTID, например, създадени при gtid_mode =ИЗКЛ.
По същия начин, за да се изчисли gtid_purged:
- Итерирайте двоичните регистрационни файлове от най-стария към най-новия, спирайки до първия двоичен регистрационен файл, който съдържа или непразен Previous_gtids_log_event (има поне един GTID) или има поне едно Gtid_log_event .
- Прочетете Previous_gtids_log_event от този файл. Изчислете вътрешната променлива gtids_in_binlog_not_purged тъй като този набор GTID се изважда от gtids_in_binlog.
- Стойност на gtid_purged е зададен на gtid_executed , минус gtids_in_binlog_not_purged .
И така, това формира основата на нашето разбиране за това как работиха нещата в по-старите версии. Въпреки това, някои оптимизации могат да бъдат направени, когато binlog_gtid_simple_recovery истина е. Това е случаят, който ни интересува:
Когато binlog_gtid_simple_recovery =ВЯРНО:
(Забележете, това е по подразбиране в MySQL 5.7.7 и по-нови)
- Прочетете само най-старите и най-новите двоични регистрационни файлове.
- Изчисли gtid_purged от Previous_gtids_log_event или Gtid_log_event намерен в най-стария двоичен регистрационен файл.
- Изчисли gtid_executed от Previous_gtids_log_event или Gtid_log_event намерен в най-новия двоичен регистрационен файл.
- По този начин, само два двоични регистрационни файла се четат по време на рестартирането на сървъра или при изчистване на двоични регистрационни файлове.
И така, за MySQL версии 5.7.7 и по-нови, най-новите и старите двоични регистрационни файлове винаги се четат по време на стартиране на системата, за да се инициализира правилно системните променливи на GTID. Четенето на най-стария двоичен регистрационен файл не е толкова скъпо, тъй като събитието, което MySQL търси, Previous_gtids_log_event, винаги е първото събитие в двоичен регистрационен файл.
Въпреки това, за да се изчисли правилно gtid_executed , сървърът трябва да прочете целия най-нов двоичен регистрационен файл и да събере всички събития в този файл. И така, времето за стартиране на системата става право пропорционално на размера на последния двоичен регистрационен файл .
Обърнете внимание, че ситуацията е още по-лоша, когато binlog_gtid_simple_recovery е FALSE . Тъй като вече не е опцията по подразбиране в последните издания, това не е особено проблем.
Как да разрешите своето бавно начално време
След като разбрахме причината за проблема, с който се сблъскахме, решението, което избрахме, беше доста очевидно – намаляване на размера на двоичните регистрационни файлове. Размерът по подразбиране на двоичните регистрационни файлове е 1GB. Отнема време за анализиране на файл с този размер по време на стартиране, така че има смисъл да се намали стойността на max_binlog_size на по-ниска стойност.
Ако намаляването на размера на двоичния регистрационен файл не е опция, тогава прочистването на двоичните регистрационни файлове точно преди спиране на поддръжката на mysqld процеса може да помогне за да намалите времето за възстановяване на binlog GTID.