Kwiecień 2018 to nie tylko data dla świata MySQL. Wydano tam MySQL 8.0, a ponad rok później prawdopodobnie nadszedł czas, aby rozważyć migrację do nowej wersji.
MySQL 8.0 ma ważne ulepszenia wydajności i bezpieczeństwa, a tak jak w przypadku każdej migracji do nowej wersji bazy danych, przed przejściem do produkcji należy wziąć pod uwagę kilka rzeczy, aby uniknąć trudnych problemów, takich jak utrata danych, nadmierna przestoju, a nawet wycofania podczas zadania migracji.
W tym blogu wspomnimy o niektórych nowych funkcjach MySQL 8.0, niektórych przestarzałych rzeczach oraz o tym, o czym należy pamiętać przed migracją.
Co nowego w MySQL 8.0?
Podsumujmy teraz niektóre z najważniejszych funkcji wymienionych w oficjalnej dokumentacji nowej wersji MySQL.
- MySQL zawiera słownik danych transakcyjnych, który przechowuje informacje o obiektach bazy danych.
- Potomna instrukcja DDL łączy aktualizacje słownika danych, operacje silnika pamięci masowej i zapisy dziennika binarnego związane z operacją DDL w jedną niepodzielną transakcję.
- Serwer MySQL automatycznie wykonuje wszystkie niezbędne zadania aktualizacji przy następnym uruchomieniu, aby zaktualizować tabele systemowe w schemacie mysql, a także obiekty w innych schematach, takich jak schemat sys i schematy użytkownika. DBA nie musi wywoływać mysql_upgrade.
- Obsługuje tworzenie i zarządzanie grupami zasobów oraz umożliwia przypisywanie wątków działających na serwerze do poszczególnych grup, tak aby wątki działały zgodnie z zasobami dostępnymi dla grupy.
- Szyfrowanie tabel można teraz zarządzać globalnie, definiując i wymuszając domyślne ustawienia szyfrowania. Zmienna default_table_encryption definiuje domyślne szyfrowanie dla nowo tworzonych schematów i ogólnego obszaru tabel. Domyślne ustawienia szyfrowania są wymuszane przez włączenie zmiennej table_encryption_privilege_check.
- Domyślny zestaw znaków zmienił się z latin1 na utf8mb4.
- Obsługuje użycie wyrażeń jako wartości domyślnych w specyfikacjach typu danych. Obejmuje to użycie wyrażeń jako wartości domyślnych dla typów danych BLOB, TEXT, GEOMETRY i JSON.
- Rejestrowanie błędów zostało przepisane na architekturę komponentu MySQL. Tradycyjne rejestrowanie błędów jest zaimplementowane przy użyciu wbudowanych komponentów, a rejestrowanie za pomocą dziennika systemowego jest zaimplementowane jako komponent ładowalny.
- Nowy typ blokady kopii zapasowej umożliwia DML podczas tworzenia kopii zapasowej online, jednocześnie uniemożliwiając operacje, które mogłyby spowodować niespójną migawkę. Nowa blokada kopii zapasowej jest obsługiwana przez składnię LOCK INSTANCE FOR BACKUP i UNLOCK INSTANCE. Do korzystania z tych instrukcji wymagane jest uprawnienie BACKUP_ADMIN.
- MySQL Server pozwala teraz na skonfigurowanie portu TCP/IP specjalnie dla połączeń administracyjnych. Stanowi to alternatywę dla pojedynczego połączenia administracyjnego, które jest dozwolone na interfejsach sieciowych używanych do zwykłych połączeń, nawet jeśli połączenia max_connections są już ustanowione.
- Obsługuje niewidoczne indeksy. Ten indeks nie jest używany przez optymalizator i umożliwia testowanie wpływu usunięcia indeksu na wydajność zapytania, bez jego usuwania.
- Sklep dokumentów do tworzenia aplikacji dokumentów SQL i NoSQL przy użyciu jednej bazy danych.
- MySQL 8.0 umożliwia utrwalanie globalnych, dynamicznych zmiennych serwera za pomocą polecenia SET PERSIST zamiast zwykłego polecenia SET GLOBAL.
Bezpieczeństwo MySQL i zarządzanie kontem
Ponieważ istnieje wiele ulepszeń związanych z bezpieczeństwem i zarządzaniem użytkownikami, wymienimy je w osobnej sekcji.
- Tabele grantów w bazie danych systemu mysql są teraz tabelami InnoDB.
- Nowa wtyczka uwierzytelniania caching_sha2_password jest teraz domyślną metodą uwierzytelniania w MySQL 8.0. Implementuje haszowanie hasła SHA-256, ale wykorzystuje buforowanie do rozwiązywania problemów z opóźnieniami w czasie połączenia. Zapewnia bezpieczniejsze szyfrowanie haseł niż wtyczka mysql_native_password i zapewnia lepszą wydajność niż sha256_password.
- MySQL obsługuje teraz role, które są nazwanymi zbiorami uprawnień. Role mogą mieć nadawane i odwoływane uprawnienia, a także mogą być nadawane i odwoływane z kont użytkowników.
- MySQL przechowuje teraz informacje o historii haseł, umożliwiając ograniczenie ponownego użycia poprzednich haseł.
- Umożliwia administratorom konfigurowanie kont użytkowników w taki sposób, że zbyt wiele kolejnych niepowodzeń logowania z powodu nieprawidłowych haseł powoduje tymczasowe zablokowanie konta.
Ulepszenia InnoDB
Podobnie jak w poprzednim punkcie, istnieje również wiele ulepszeń związanych z tym tematem, więc wymienimy je również w osobnej sekcji.
- Aktualna maksymalna wartość licznika automatycznego przyrostu jest zapisywana w dzienniku ponawiania przy każdej zmianie wartości i zapisywana w prywatnej tabeli systemu silnika w każdym punkcie kontrolnym. Te zmiany sprawiają, że aktualna maksymalna wartość licznika auto-inkrementacji jest trwała podczas restartów serwera
- Podczas napotkania uszkodzenia drzewa indeksu, InnoDB zapisuje flagę uszkodzenia do dziennika przeróbek, dzięki czemu flaga uszkodzenia jest bezpieczna w razie awarii. InnoDB zapisuje również dane o znacznikach uszkodzenia pamięci w prywatnej tabeli systemowej silnika w każdym punkcie kontrolnym. Podczas odzyskiwania InnoDB odczytuje flagi uszkodzenia z obu lokalizacji i łączy wyniki przed oznaczeniem tabeli w pamięci i obiektów indeksu jako uszkodzonych.
- Nowa zmienna dynamiczna, innodb_deadlock_detect, może zostać użyta do wyłączenia wykrywania zakleszczeń. W systemach o wysokiej współbieżności wykrywanie zakleszczeń może spowodować spowolnienie, gdy wiele wątków czeka na tę samą blokadę. Czasami bardziej wydajne może być wyłączenie wykrywania zakleszczeń i poleganie na ustawieniu innodb_lock_wait_timeout w celu wycofania transakcji po wystąpieniu zakleszczenia.
- Tabele tymczasowe InnoDB są teraz tworzone we współdzielonym tymczasowym obszarze tabel, ibtmp1.
- Tabele systemowe mysql i tabele słowników danych są teraz tworzone w pojedynczym pliku obszaru tabel InnoDB o nazwie mysql.ibd w katalogu danych MySQL. Wcześniej te tabele były tworzone w osobnych plikach przestrzeni tabel InnoDB w katalogu bazy danych mysql.
- Domyślnie dzienniki cofania znajdują się teraz w dwóch obszarach tabel cofania, które są tworzone podczas inicjowania instancji MySQL. Dzienniki cofania nie są już tworzone w systemowej przestrzeni tabel.
- Nowa zmienna innodb_dedicated_server, która jest domyślnie wyłączona, może służyć do automatycznego konfigurowania przez InnoDB następujących opcji w zależności od ilości pamięci wykrytej na serwerze:innodb_buffer_pool_size, innodb_log_file_size i innodb_flush_method. Ta opcja jest przeznaczona dla instancji serwera MySQL, które działają na serwerze dedykowanym.
- Pliki obszaru tabel można przenosić lub przywracać do nowej lokalizacji, gdy serwer jest w trybie offline, za pomocą opcji innodb_directories.
Teraz przyjrzyjmy się niektórym funkcjom, których nie powinieneś już używać w tej nowej wersji MySQL.
Co jest przestarzałe w MySQL 8.0?
Następujące funkcje są przestarzałe i zostaną usunięte w przyszłej wersji.
- Zestaw znaków utf8mb3 jest przestarzały. Zamiast tego użyj utf8mb4.
- Ponieważ caching_sha2_password jest domyślną wtyczką uwierzytelniającą w MySQL 8.0 i zapewnia nadzbiór możliwości wtyczki uwierzytelniającej sha256_password, sha256_password jest przestarzałe.
- Wtyczka validate_password została ponownie zaimplementowana w celu korzystania z infrastruktury komponentów serwera. Forma wtyczki validate_password jest nadal dostępna, ale jest przestarzała.
- Klauzula ENGINE dla instrukcji ALTER TABLESPACE i DROP TABLESPACE.
- Tryb SQL PAD_CHAR_TO_FULL_LENGTH.
- Obsługa AUTO_INCREMENT jest przestarzała dla kolumn typu FLOAT i DOUBLE (i dowolnych synonimów). Rozważ usunięcie atrybutu AUTO_INCREMENT z takich kolumn lub przekonwertuj je na typ całkowity.
- Atrybut UNSIGNED jest przestarzały dla kolumn typu FLOAT, DOUBLE i DECIMAL (i dowolnych synonimów). Rozważ użycie prostego ograniczenia CHECK dla takich kolumn.
- Składnia FLOAT(M,D) i DOUBLE(M,D) określająca liczbę cyfr dla kolumn typu FLOAT i DOUBLE (i dowolnych synonimów) jest niestandardowym rozszerzeniem MySQL. Ta składnia jest przestarzała.
- Niestandardowe &&, || i ! Operatory będące synonimami standardowych operatorów SQL AND, OR i NOT są przestarzałe. Aplikacje używające niestandardowych operatorów powinny być dostosowane do używania standardowych operatorów.
- Klient mysql_upgrade jest przestarzały, ponieważ jego możliwości uaktualniania tabel systemowych w schemacie systemu mysql i obiektów w innych schematach zostały przeniesione na serwer MySQL.
- Plik mysql_upgrade_info, który jest tworzonym katalogiem danych i używanym do przechowywania numeru wersji MySQL.
- Zmienna systemowa relay_log_info_file i opcja --master-info-file są przestarzałe. Wcześniej były one używane do określenia nazwy dziennika informacyjnego dziennika przekazywania i głównego dziennika informacyjnego, gdy ustawione były relay_log_info_repository=PLIK i master_info_repository=PLIK, ale te ustawienia są przestarzałe. Używanie plików dla dziennika informacyjnego dziennika przekaźnika i dziennika głównego informacji zostało zastąpione przez bezpieczne w razie awarii tabele podrzędne, które są domyślne w MySQL 8.0.
- Użycie zmiennej środowiskowej MYSQL_PWD do określenia hasła MySQL jest przestarzałe.
A teraz przyjrzyjmy się niektórym funkcjom, których musisz przestać używać w tej wersji MySQL.
Co zostało usunięte w MySQL 8.0?
Następujące funkcje zostały usunięte w MySQL 8.0.
- Zmienna systemowa innodb_locks_unsafe_for_binlog została usunięta. Poziom izolacji READ COMMITTED zapewnia podobną funkcjonalność.
- Korzystanie z GRANT do tworzenia użytkowników. Zamiast tego użyj CREATE USER. Postępowanie zgodnie z tą praktyką sprawia, że tryb SQL NO_AUTO_CREATE_USER jest nieistotny dla instrukcji GRANT, więc również jest usuwany, a błąd jest teraz zapisywany w dzienniku serwera, gdy obecność tej wartości dla opcji sql_mode w pliku opcji uniemożliwia uruchomienie mysqld.
- Korzystanie z GRANT do modyfikowania właściwości konta innych niż przypisywanie uprawnień. Obejmuje to uwierzytelnianie, SSL i właściwości limitu zasobów. Zamiast tego ustal takie właściwości w momencie tworzenia konta za pomocą CREATE USER lub zmodyfikuj je później za pomocą ALTER USER.
- IDENTYFIKOWANE PRZEZ HASŁO Składnia 'auth_string' dla CREATE USER i GRANT. Zamiast tego użyj IDENTIFIED WITH auth_plugin AS „auth_string” dla CREATE USER i ALTER USER, gdzie wartość „auth_string” jest w formacie zgodnym z nazwaną wtyczką.
- Funkcja HASŁO(). Dodatkowo usunięcie PASSWORD() oznacza, że składnia SET PASSWORD ... =PASSWORD('auth_string') nie jest już dostępna.
- Zmienna systemowa old_passwords.
- Instrukcje FLUSH QUERY CACHE i RESET QUERY CACHE.
- Te zmienne systemowe:query_cache_limit, query_cache_min_res_unit, query_cache_size, query_cache_type, query_cache_wlock_invalidate.
- Te zmienne stanu:Qcache_free_blocks, Qcache_free_memory, Qcache_hits, Qcache_inserts, Qcache_lowmem_prunes, Qcache_not_cached, Qcache_queries_in_cache, Qcache_total_blocks.
- Te stany wątku:sprawdzanie uprawnień do buforowanego zapytania, sprawdzanie pamięci podręcznej zapytań dla zapytania, unieważnianie wpisów w pamięci podręcznej zapytań, wysyłanie zbuforowanych wyników do klienta, przechowywanie wyników w pamięci podręcznej zapytań, oczekiwanie na blokadę pamięci podręcznej zapytań.
- Zmienne systemowe tx_isolation i tx_read_only zostały usunięte. Zamiast tego użyj transaction_isolation i transaction_read_only.
- Zmienna systemowa sync_frm została usunięta, ponieważ pliki .frm stały się przestarzałe.
- Zmienna systemowa secure_auth i opcja klienta --secure-auth zostały usunięte. Usunięto opcję MYSQL_SECURE_AUTH dla funkcji mysql_options() C API.
- Zmienna systemowa log_warnings i opcja serwera --log-warnings zostały usunięte. Zamiast tego użyj zmiennej systemowej log_error_verbosity.
- Globalny zakres zmiennej systemowej sql_log_bin został usunięty. sql_log_bin ma tylko zakres sesji, a aplikacje, które opierają się na dostępie do @@GLOBAL.sql_log_bin, powinny zostać dostosowane.
- Nieużywane zmienne systemowe date_format, datetime_format, time_format i max_tmp_tables są usuwane.
- Nieaktualne kwalifikatory ASC lub DESC dla klauzul GROUP BY są usuwane. Zapytania, które wcześniej opierały się na sortowaniu GROUP BY, mogą dawać wyniki, które różnią się od poprzednich wersji MySQL. Aby utworzyć daną kolejność sortowania, podaj klauzulę ORDER BY.
- Parser nie traktuje już \N jako synonimu NULL w instrukcjach SQL. Zamiast tego użyj wartości NULL. Ta zmiana nie wpływa na operacje importu lub eksportu plików tekstowych wykonywane za pomocą funkcji LOAD DATA lub SELECT ... INTO OUTFILE, dla których NULL jest nadal reprezentowane przez \N.
- Opcje --ssl i --ssl-verify-server-cert po stronie klienta zostały usunięte. Użyj --ssl-mode=WYMAGANE zamiast --ssl=1 lub --enable-ssl. Użyj opcji --ssl-mode=WYŁĄCZONE zamiast --ssl=0, --skip-ssl lub --disable-ssl. Użyj opcji --ssl-mode=VERIFY_IDENTITY zamiast --ssl-verify-server-cert.
- Program mysql_install_db został usunięty z dystrybucji MySQL. Inicjalizację katalogu danych należy wykonać poprzez wywołanie mysqld z opcją --initialize lub --initialize-insecure. Ponadto usunięto opcję --bootstrap dla mysqld, która była używana przez mysql_install_db, oraz usunięto opcję INSTALL_SCRIPTDIR CMake, która kontrolowała lokalizację instalacji mysql_install_db.
- Narzędzie mysql_plugin zostało usunięte. Alternatywy obejmują ładowanie wtyczek podczas uruchamiania serwera za pomocą opcji --plugin-load lub --plugin-load-add lub w czasie wykonywania za pomocą instrukcji INSTALL PLUGIN.
- Narzędzie resolveip zostało usunięte. Zamiast tego można użyć nslookup, host lub dig.
Istnieje wiele nowych, przestarzałych i usuniętych funkcji. Możesz sprawdzić oficjalną stronę internetową, aby uzyskać bardziej szczegółowe informacje.
Rozważania przed migracją do MySQL 8.0
Wspomnijmy teraz o kilku najważniejszych rzeczach do rozważenia przed migracją do tej wersji MySQL.
Metoda uwierzytelniania
Jak wspomnieliśmy, caching_sha2_password nie jest domyślną metodą uwierzytelniania, więc powinieneś sprawdzić, czy Twoja aplikacja/konektor ją obsługuje. Jeśli nie, zobaczmy, jak ponownie zmienić domyślną metodę uwierzytelniania i wtyczkę uwierzytelniania użytkownika na „mysql_native_password”.
Aby zmienić domyślną metodę uwierzytelniania, edytuj plik konfiguracyjny my.cnf i dodaj/edytuj następujący wiersz:
$ vi /etc/my.cnf
[mysqld]
default_authentication_plugin=mysql_native_password
Aby zmienić wtyczkę uwierzytelniania użytkownika, uruchom następujące polecenie z uprzywilejowanym użytkownikiem:
$ mysql -p
ALTER USER ‘username’@’hostname’ IDENTIFIED WITH ‘mysql_native_password’ BY ‘password’;
W każdym razie te zmiany nie są trwałym rozwiązaniem, ponieważ stare uwierzytelnianie może wkrótce zostać wycofane, więc należy wziąć je pod uwagę przy przyszłej aktualizacji bazy danych.
Ważną cechą są tu również role. Możesz zmniejszyć indywidualne uprawnienia przypisując go do roli i dodając tam odpowiednich użytkowników.
Możesz na przykład utworzyć nową rolę dla zespołów marketingu i programistów:
$ mysql -p
CREATE ROLE 'marketing', 'developers';
Przypisz uprawnienia do tych nowych ról:
GRANT SELECT ON *.* TO 'marketing';
GRANT ALL PRIVILEGES ON *.* TO 'developers';
Następnie przypisz role użytkownikom:
GRANT 'marketing' TO 'marketing1'@'%';
GRANT 'marketing' TO 'marketing2'@'%';
GRANT 'developers' TO 'developer1'@'%';
I to wszystko. Będziesz mieć następujące uprawnienia:
SHOW GRANTS FOR 'marketing1'@'%';
+-------------------------------------------+
| Grants for [email protected]% |
+-------------------------------------------+
| GRANT USAGE ON *.* TO `marketing1`@`%` |
| GRANT `marketing`@`%` TO `marketing1`@`%` |
+-------------------------------------------+
2 rows in set (0.00 sec)
SHOW GRANTS FOR 'marketing';
+----------------------------------------+
| Grants for [email protected]% |
+----------------------------------------+
| GRANT SELECT ON *.* TO `marketing`@`%` |
+----------------------------------------+
1 row in set (0.00 sec)
Zestawy znaków
Ponieważ nowy domyślny zestaw znaków to utf8mb4, powinieneś upewnić się, że nie używasz domyślnego, ponieważ się zmieni.
Aby uniknąć niektórych problemów, należy określić zmienne character_set_server i collation_server w pliku konfiguracyjnym my.cnf.
$ vi /etc/my.cnf
[mysqld]
character_set_server=latin1
collation_server=latin1_swedish_ci
Silnik MyISAM
Tabele uprawnień MySQL w schemacie MySQL są przenoszone do InnoDB. Możesz utworzyć silnik tabel=MyISAM, który będzie działał jak poprzednio, ale skopiowanie tabeli MyISAM do działającego serwera MySQL nie zadziała, ponieważ nie zostanie wykryty.
Partycjonowanie
Nie mogą istnieć tabele partycjonowane, które korzystają z aparatu pamięci masowej, który nie obsługuje natywnego partycjonowania. Możesz uruchomić następujące zapytanie, aby zweryfikować ten punkt.
$ mysql -p
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE NOT IN ('innodb', 'ndbcluster') AND CREATE_OPTIONS LIKE '%partitioned%';
Jeśli chcesz zmienić silnik tabeli, możesz uruchomić:
ALTER TABLE table_name ENGINE = INNODB;
Sprawdzenie aktualizacji
W ostatnim kroku możesz uruchomić polecenie mysqlcheck za pomocą flagi check-upgrade, aby potwierdzić, czy wszystko wygląda dobrze.
$ mysqlcheck -uroot -p --all-databases --check-upgrade
Enter password:
mysql.columns_priv OK
mysql.component OK
mysql.db OK
mysql.default_roles OK
mysql.engine_cost OK
mysql.func OK
mysql.general_log OK
mysql.global_grants OK
mysql.gtid_executed OK
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
mysql.help_topic OK
mysql.innodb_index_stats OK
mysql.innodb_table_stats OK
mysql.password_history OK
mysql.plugin OK
mysql.procs_priv OK
mysql.proxies_priv OK
mysql.role_edges OK
mysql.server_cost OK
mysql.servers OK
mysql.slave_master_info OK
mysql.slave_relay_log_info OK
mysql.slave_worker_info OK
mysql.slow_log OK
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
mysql.time_zone_name OK
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
sys.sys_config OK
world_x.city OK
world_x.country OK
world_x.countryinfo OK
world_x.countrylanguage OK
Przed wykonaniem aktualizacji należy sprawdzić kilka rzeczy. Możesz sprawdzić oficjalną dokumentację MySQL, aby uzyskać bardziej szczegółowe informacje.
Metody aktualizacji
Istnieją różne sposoby aktualizacji MySQL 5.7 do 8.0. Możesz użyć uaktualnienia na miejscu lub nawet utworzyć podrzędną replikację w nowej wersji, aby móc ją później promować.
Ale przed aktualizacją, w kroku 0 należy utworzyć kopię zapasową danych. Kopia zapasowa powinna obejmować wszystkie bazy danych, w tym bazy systemowe. Tak więc, jeśli wystąpi jakiś problem, możesz wycofać się jak najszybciej.
Inną opcją, w zależności od dostępnych zasobów, może być utworzenie replikacji kaskadowej MySQL 5.7 -> MySQL 8.0 -> MySQL 5.7, więc po wypromowaniu nowej wersji, jeśli coś poszło nie tak, można promować węzeł podrzędny ze starą wersją z powrotem. Ale może to być niebezpieczne, jeśli wystąpił jakiś problem z danymi, więc kopia zapasowa jest koniecznością przed nią.
Dla każdej metody, która ma być użyta, konieczne jest środowisko testowe, aby sprawdzić, czy aplikacja działa bez żadnych problemów przy użyciu nowej wersji MySQL 8.0.
Wnioski
Ponad rok po wydaniu MySQL 8.0 nadszedł czas, aby zacząć myśleć o migracji starej wersji MySQL, ale na szczęście koniec wsparcia dla MySQL 5.7 to rok 2023, masz czas na stworzenie planu migracji i przetestowanie zachowania aplikacji bez pośpiechu. Poświęcenie trochę czasu na ten etap testowania jest konieczne, aby uniknąć problemów po migracji.