Базите данни с отворен код бързо стават масови, така че миграцията от собствени двигатели към двигатели с отворен код сега е вид тенденция в индустрията. Това също така означава, че ние, DBA, често в крайна сметка разполагаме с множество сървъри на база данни за управление.
В последните няколко публикации в блога, моят колега Пол Намуаг и аз покрихме няколко аспекта на миграцията от Oracle към Percona, MariaDB и MySQL. Очевидната цел на миграцията е приложението ви да работи по-ефективно в новата среда на база данни, но е от решаващо значение да се гарантира, че персоналът е готов да го поддържа.
Този блог обхваща основните операции на MySQL с позоваване на подобни задачи, които бихте изпълнявали ежедневно във вашата среда на Oracle. Той ви предоставя задълбочено разглеждане на различни теми, за да ви спести време, тъй като можете да се свържете със знанията на Oracle, които вече сте изградили през годините.
Ще говорим и за външни инструменти за команден ред, които липсват в инсталацията на MySQL по подразбиране, но са необходими за ефективно извършване на ежедневни операции. Версията с отворен код не се предлага с еквивалента на Oracle Cloud Control например, така че проверете ClusterControl, ако търсите нещо подобно.
В този блог предполагаме, че имате по-добри познания за Oracle от MySQL и следователно бихте искали да знаете връзката между двете. Примерите са базирани на Linux платформа, но можете да намерите много прилики в управлението на MySQL в Windows.
Как да се свържа с MySQL?
Нека започнем нашето пътуване с една много (привидно) основна задача. Всъщност това е вид задача, която може да предизвика известно объркване поради различни концепции за влизане в Oracle и MySQL.
Еквивалентът на sqlplus / като sysdba връзка е “mysql” терминална команда с флаг -uroot. В света на MySQL суперпотребителят се нарича root. Потребителите на MySQL база данни (включително root) се дефинират от името и хоста, откъдето може да се свърже.
Информацията за потребителя и хостовете, откъдето може да се свърже, се съхранява в таблицата mysql.user. При опита за свързване MySQL проверява дали хостът на клиента, потребителското име и паролата съвпадат с реда в таблицата с метаданни.
Това е малко по-различен подход от този в Oracle, където имаме само потребителско име и парола, но тези, които са запознати с Oracle Connection Manager, може да открият някои прилики.
Няма да намерите предварително дефинирани TNS записи като в Oracle. Обикновено за връзка с администратор се нуждаем от потребител, парола и -h флаг за хост. Портът по подразбиране е 3306 (като 1521 в Oracle), но това може да варира при различните настройки.
По подразбиране много инсталации ще имат блокирана връзка за root достъп от всяка машина ([email protected]’%’), така че трябва да влезете в сървъра, хостващ MySQL, обикновено чрез ssh.
Въведете следното:
mysql -u root
Когато root паролата не е зададена, това е достатъчно. Ако се изисква парола, трябва да добавите флага -p.
mysql -u root -p
Вече сте влезли в mysql клиента (еквивалент на sqlplus) и ще видите подкана, обикновено 'mysql>'.
MySQL работи ли е?
Можете да използвате скрипта за стартиране на услугата mysql или командата mysqladmin, за да разберете дали работи. След това можете да използвате командата ps, за да видите дали процесите на mysql са стартирани и работят. Друга алтернатива може да бъде mysqladmin, която е помощна програма, която се използва за извършване на административни операции.
mysqladmin -u root -p status
На Debian:
/etc/init.d/mysql status
Ако използвате RedHat или Fedora, тогава можете да използвате следния скрипт:
service mysqld status
Или
/etc/init.d/mysqld status
Или
systemctl status mysql.service
В екземпляри на MariaDB трябва да потърсите името на услугата MariaDB.
systemctl status mariadb
Какво има в тази база данни?
Подобно на Oracle, можете да запитвате обектите с метаданни, за да получите информация за обектите на базата данни.
Тук е обичайно да използвате някои преки пътища, команди, които ви помагат да изброите обекти или да получите DDL на обектите.
show databases;
use database_name;
show tables;
show table status;
show index from table_name;
show create table table_name;
Подобно на Oracle можете да опишете таблицата:
desc table_name;
Къде се съхраняват моите данни?
Няма специална вътрешна памет като ASM в MySQL. Всички файлове с данни се поставят в обикновените точки за монтиране на ОС. С инсталация по подразбиране можете да намерите вашите данни в:
/var/lib/mysql
Местоположението се основава на променливата datadir.
[email protected]:~# cat /etc/mysql/my.cnf | grep datadir
datadir=/var/lib/mysql
Там ще видите директория за всяка база данни.
В зависимост от версията и механизма за съхранение (да, има няколко тук), директорията на базата данни може да съдържа файлове с формат *.frm, които дефинират структурата на всяка таблица в базата данни. За MyISAM таблици данните (*.MYD) и индексите (*.MYI) също се съхраняват в тази директория.
Таблиците InnoDB се съхраняват в пространства за таблици InnoDB. Всеки от тях се състои от един или повече файлове, които са подобни на пространствата за таблици на Oracle. При инсталация по подразбиране всички InnoDB данни и индекси за всички бази данни на MySQL сървър се съхраняват в едно пространство за таблици, състоящо се от един файл:/var/lib/mysql/ibdata1. В повечето настройки не управлявате пространства за таблици, както в Oracle. Най-добрата практика е да ги поддържате с включено автоматично удължаване и неограничен максимален размер.
[email protected]:~# cat /etc/mysql/my.cnf | grep innodb-data-file-path
innodb-data-file-path = ibdata1:100M:autoextend
InnoDB има регистрационни файлове, които са еквивалент на регистрационните файлове за повторно изпълнение на Oracle, позволяващи автоматично възстановяване при срив. По подразбиране има два регистрационни файла:/var/lib/mysql/ib_logfile0 и /var/lib/mysql/ib_logfile1. Данните за отмяна се съхраняват във файла на пространството за таблици.
[email protected]:/var/lib/mysql# ls -rtla | grep logfile
-rw-rw---- 1 mysql mysql 268435456 Dec 15 00:59 ib_logfile1
-rw-rw---- 1 mysql mysql 268435456 Mar 6 11:45 ib_logfile0
Къде е информацията за метаданните?
Няма изгледи от типа dba_*, user_*, all_*, но MySQL има вътрешни изгледи с метаданни.
Information_schema е дефинирана в стандарта SQL 2003 и се изпълнява от други основни бази данни, напр. SQL Server, PostgreSQL.
От MySQL 5.0 е налична базата данни information_schema, съдържаща информация от речника на данните. Информацията всъщност се съхранява във външните FRM файлове. И накрая, след много години .frm файловете са изчезнали във версия 8.0. Метаданните все още са видими в базата данни information_schema, но използват механизма за съхранение на InnoDB.
За да видите всички действителни изгледи, съдържащи се в речника на данните в mysql клиента, превключете към база данни information_schema:
use information_schema;
show tables;
Можете да намерите допълнителна информация в базата данни MySQL, която съдържа информация за db, събитие (задания на MySQL), плъгини, репликация, база данни, потребители и т.н.
Броят на показванията зависи от версията и доставчика.
Изберете * от v$session
Изборът * на Oracle от v$session е представен тук с командата SHOW PROCESSLIST, която показва списъка с нишки.
mysql> SHOW PROCESSLIST;
+---------+------------------+------------------+--------------------+---------+--------+--------------------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+---------+------------------+------------------+--------------------+---------+--------+--------------------+------------------+-----------+---------------+
| 1 | system user | | NULL | Sleep | 469264 | wsrep aborter idle | NULL | 0 | 0 |
| 2 | system user | | NULL | Sleep | 469264 | NULL | NULL | 0 | 0 |
| 3 | system user | | NULL | Sleep | 469257 | NULL | NULL | 0 | 0 |
| 4 | system user | | NULL | Sleep | 469257 | NULL | NULL | 0 | 0 |
| 6 | system user | | NULL | Sleep | 469257 | NULL | NULL | 0 | 0 |
| 16 | maxscale | 10.0.3.168:5914 | NULL | Sleep | 5 | | NULL | 4 | 4 |
| 59 | proxysql-monitor | 10.0.3.168:6650 | NULL | Sleep | 7 | | NULL | 0 | 0 |
| 81 | proxysql-monitor | 10.0.3.78:62896 | NULL | Sleep | 6 | | NULL | 0 | 0 |
| 1564 | proxysql-monitor | 10.0.3.78:25064 | NULL | Sleep | 3 | | NULL | 0 | 0 |
| 1822418 | cmon | 10.0.3.168:41202 | information_schema | Sleep | 0 | | NULL | 0 | 8 |
| 1822631 | cmon | 10.0.3.168:43254 | information_schema | Sleep | 4 | | NULL | 1 | 1 |
| 1822646 | cmon | 10.0.3.168:43408 | information_schema | Sleep | 0 | | NULL | 464 | 464 |
| 2773260 | backupuser | localhost | mysql | Query | 0 | init | SHOW PROCESSLIST | 0 | 0 |
+---------+------------------+------------------+--------------------+---------+--------+--------------------+------------------+-----------+---------------+
13 rows in set (0.00 sec)
Той се основава на информация, съхранявана в изгледа information_schema.processlist. Изгледът изисква да има привилегия PROCESS. Освен това може да ви помогне да проверите дали не ви изчерпва максималният брой процеси.
Къде е дневник за сигнали?
Регистърът на грешките може да бъде намерен в my.cnf или чрез командата show variables.
mysql> show variables like 'log_error';
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| log_error | /var/lib/mysql/error.log |
+---------------+--------------------------+
1 row in set (0.00 sec)
Къде е списъкът с потребителите и техните разрешения?
Информацията за потребителите се съхранява в таблицата mysql.user, докато грантовете се съхраняват на няколко места, включително mysql.user, mysql.tables_priv,
Потребителският достъп до MySQL е дефиниран в:
mysql.columns_priv, mysql.tables_priv, mysql.db,mysql.user
Предпочитаният начин за изброяване на грантове е да използвате pt-grants, инструмента от инструментариума Percona (задължителен за всеки MySQL DBA).
pt-show-grants --host localhost --user root --ask-pass
Като алтернатива можете да използвате следната заявка (създадена от Calvaldo)
SELECT
CONCAT("`",gcl.Db,"`") AS 'Database(s) Affected',
CONCAT("`",gcl.Table_name,"`") AS 'Table(s) Affected',
gcl.User AS 'User-Account(s) Affected',
IF(gcl.Host='%','ALL',gcl.Host) AS 'Remote-IP(s) Affected',
CONCAT("GRANT ",UPPER(gcl.Column_priv)," (",GROUP_CONCAT(gcl.Column_name),") ",
"ON `",gcl.Db,"`.`",gcl.Table_name,"` ",
"TO '",gcl.User,"'@'",gcl.Host,"';") AS 'GRANT Statement (Reconstructed)'
FROM mysql.columns_priv gcl
GROUP BY CONCAT(gcl.Db,gcl.Table_name,gcl.User,gcl.Host)
/* SELECT * FROM mysql.columns_priv */
UNION
/* [Database.Table]-Specific Grants */
SELECT
CONCAT("`",gtb.Db,"`") AS 'Database(s) Affected',
CONCAT("`",gtb.Table_name,"`") AS 'Table(s) Affected',
gtb.User AS 'User-Account(s) Affected',
IF(gtb.Host='%','ALL',gtb.Host) AS 'Remote-IP(s) Affected',
CONCAT(
"GRANT ",UPPER(gtb.Table_priv)," ",
"ON `",gtb.Db,"`.`",gtb.Table_name,"` ",
"TO '",gtb.User,"'@'",gtb.Host,"';"
) AS 'GRANT Statement (Reconstructed)'
FROM mysql.tables_priv gtb
WHERE gtb.Table_priv!=''
/* SELECT * FROM mysql.tables_priv */
UNION
/* Database-Specific Grants */
SELECT
CONCAT("`",gdb.Db,"`") AS 'Database(s) Affected',
"ALL" AS 'Table(s) Affected',
gdb.User AS 'User-Account(s) Affected',
IF(gdb.Host='%','ALL',gdb.Host) AS 'Remote-IP(s) Affected',
CONCAT(
'GRANT ',
CONCAT_WS(',',
IF(gdb.Select_priv='Y','SELECT',NULL),
IF(gdb.Insert_priv='Y','INSERT',NULL),
IF(gdb.Update_priv='Y','UPDATE',NULL),
IF(gdb.Delete_priv='Y','DELETE',NULL),
IF(gdb.Create_priv='Y','CREATE',NULL),
IF(gdb.Drop_priv='Y','DROP',NULL),
IF(gdb.Grant_priv='Y','GRANT',NULL),
IF(gdb.References_priv='Y','REFERENCES',NULL),
IF(gdb.Index_priv='Y','INDEX',NULL),
IF(gdb.Alter_priv='Y','ALTER',NULL),
IF(gdb.Create_tmp_table_priv='Y','CREATE TEMPORARY TABLES',NULL),
IF(gdb.Lock_tables_priv='Y','LOCK TABLES',NULL),
IF(gdb.Create_view_priv='Y','CREATE VIEW',NULL),
IF(gdb.Show_view_priv='Y','SHOW VIEW',NULL),
IF(gdb.Create_routine_priv='Y','CREATE ROUTINE',NULL),
IF(gdb.Alter_routine_priv='Y','ALTER ROUTINE',NULL),
IF(gdb.Execute_priv='Y','EXECUTE',NULL),
IF(gdb.Event_priv='Y','EVENT',NULL),
IF(gdb.Trigger_priv='Y','TRIGGER',NULL)
),
" ON `",gdb.Db,"`.* TO '",gdb.User,"'@'",gdb.Host,"';"
) AS 'GRANT Statement (Reconstructed)'
FROM mysql.db gdb
WHERE gdb.Db != ''
/* SELECT * FROM mysql.db */
UNION
/* User-Specific Grants */
SELECT
"ALL" AS 'Database(s) Affected',
"ALL" AS 'Table(s) Affected',
gus.User AS 'User-Account(s) Affected',
IF(gus.Host='%','ALL',gus.Host) AS 'Remote-IP(s) Affected',
CONCAT(
"GRANT ",
IF((gus.Select_priv='N')&(gus.Insert_priv='N')&(gus.Update_priv='N')&(gus.Delete_priv='N')&(gus.Create_priv='N')&(gus.Drop_priv='N')&(gus.Reload_priv='N')&(gus.Shutdown_priv='N')&(gus.Process_priv='N')&(gus.File_priv='N')&(gus.References_priv='N')&(gus.Index_priv='N')&(gus.Alter_priv='N')&(gus.Show_db_priv='N')&(gus.Super_priv='N')&(gus.Create_tmp_table_priv='N')&(gus.Lock_tables_priv='N')&(gus.Execute_priv='N')&(gus.Repl_slave_priv='N')&(gus.Repl_client_priv='N')&(gus.Create_view_priv='N')&(gus.Show_view_priv='N')&(gus.Create_routine_priv='N')&(gus.Alter_routine_priv='N')&(gus.Create_user_priv='N')&(gus.Event_priv='N')&(gus.Trigger_priv='N')&(gus.Create_tablespace_priv='N')&(gus.Grant_priv='N'),
"USAGE",
IF((gus.Select_priv='Y')&(gus.Insert_priv='Y')&(gus.Update_priv='Y')&(gus.Delete_priv='Y')&(gus.Create_priv='Y')&(gus.Drop_priv='Y')&(gus.Reload_priv='Y')&(gus.Shutdown_priv='Y')&(gus.Process_priv='Y')&(gus.File_priv='Y')&(gus.References_priv='Y')&(gus.Index_priv='Y')&(gus.Alter_priv='Y')&(gus.Show_db_priv='Y')&(gus.Super_priv='Y')&(gus.Create_tmp_table_priv='Y')&(gus.Lock_tables_priv='Y')&(gus.Execute_priv='Y')&(gus.Repl_slave_priv='Y')&(gus.Repl_client_priv='Y')&(gus.Create_view_priv='Y')&(gus.Show_view_priv='Y')&(gus.Create_routine_priv='Y')&(gus.Alter_routine_priv='Y')&(gus.Create_user_priv='Y')&(gus.Event_priv='Y')&(gus.Trigger_priv='Y')&(gus.Create_tablespace_priv='Y')&(gus.Grant_priv='Y'),
"ALL PRIVILEGES",
CONCAT_WS(',',
IF(gus.Select_priv='Y','SELECT',NULL),
IF(gus.Insert_priv='Y','INSERT',NULL),
IF(gus.Update_priv='Y','UPDATE',NULL),
IF(gus.Delete_priv='Y','DELETE',NULL),
IF(gus.Create_priv='Y','CREATE',NULL),
IF(gus.Drop_priv='Y','DROP',NULL),
IF(gus.Reload_priv='Y','RELOAD',NULL),
IF(gus.Shutdown_priv='Y','SHUTDOWN',NULL),
IF(gus.Process_priv='Y','PROCESS',NULL),
IF(gus.File_priv='Y','FILE',NULL),
IF(gus.References_priv='Y','REFERENCES',NULL),
IF(gus.Index_priv='Y','INDEX',NULL),
IF(gus.Alter_priv='Y','ALTER',NULL),
IF(gus.Show_db_priv='Y','SHOW DATABASES',NULL),
IF(gus.Super_priv='Y','SUPER',NULL),
IF(gus.Create_tmp_table_priv='Y','CREATE TEMPORARY TABLES',NULL),
IF(gus.Lock_tables_priv='Y','LOCK TABLES',NULL),
IF(gus.Execute_priv='Y','EXECUTE',NULL),
IF(gus.Repl_slave_priv='Y','REPLICATION SLAVE',NULL),
IF(gus.Repl_client_priv='Y','REPLICATION CLIENT',NULL),
IF(gus.Create_view_priv='Y','CREATE VIEW',NULL),
IF(gus.Show_view_priv='Y','SHOW VIEW',NULL),
IF(gus.Create_routine_priv='Y','CREATE ROUTINE',NULL),
IF(gus.Alter_routine_priv='Y','ALTER ROUTINE',NULL),
IF(gus.Create_user_priv='Y','CREATE USER',NULL),
IF(gus.Event_priv='Y','EVENT',NULL),
IF(gus.Trigger_priv='Y','TRIGGER',NULL),
IF(gus.Create_tablespace_priv='Y','CREATE TABLESPACE',NULL)
)
)
),
" ON *.* TO '",gus.User,"'@'",gus.Host,"' REQUIRE ",
CASE gus.ssl_type
WHEN 'ANY' THEN
"SSL "
WHEN 'X509' THEN
"X509 "
WHEN 'SPECIFIED' THEN
CONCAT_WS("AND ",
IF((LENGTH(gus.ssl_cipher)>0),CONCAT("CIPHER '",CONVERT(gus.ssl_cipher USING utf8),"' "),NULL),
IF((LENGTH(gus.x509_issuer)>0),CONCAT("ISSUER '",CONVERT(gus.ssl_cipher USING utf8),"' "),NULL),
IF((LENGTH(gus.x509_subject)>0),CONCAT("SUBJECT '",CONVERT(gus.ssl_cipher USING utf8),"' "),NULL)
)
ELSE "NONE "
END,
"WITH ",
IF(gus.Grant_priv='Y',"GRANT OPTION ",""),
"MAX_QUERIES_PER_HOUR ",gus.max_questions," ",
"MAX_CONNECTIONS_PER_HOUR ",gus.max_connections," ",
"MAX_UPDATES_PER_HOUR ",gus.max_updates," ",
"MAX_USER_CONNECTIONS ",gus.max_user_connections,
";"
) AS 'GRANT Statement (Reconstructed)'
FROM mysql.user gus;
Как да създадете потребител на mysql
Процедурата за създаване на потребител е подобна на Oracle. Най-простият пример може да бъде:
CREATE user 'username'@'hostname' identified by 'password';
GRANT privilege_name on *.* TO 'username'@'hostname';
Опцията за предоставяне и създаване на един ред с:
GRANT privilege_name ON *.* TO 'username'@'hostname' identified by 'password';
е премахнат в MySQL 8.0.
Как да стартирам и спра MySQL?
Можете да спрете и стартирате MySQL с услугата.
Действителната команда зависи от дистрибуцията на Linux и името на услугата.
По-долу можете да намерите пример с името на услугата mysqld.
Ubuntu
/etc/init.d/mysqld start
/etc/init.d/mysqld stop
/etc/init.d/mysqld restart
RedHat/Centos
service mysqld start
service mysqld stop
service mysqld restart
systemctl start mysqld.service
systemctl stop mysqld.service
systemctl restart mysqld.service
Къде са данните за конфигурацията на MySQL сървъра?
Конфигурацията се съхранява във файла my.cnf.
До версия 8.0 всяка промяна на динамични настройки, която трябва да остане след рестарт, изисква ръчна актуализация на файла my.cnf. Подобно на Scope=both на Oracle, можете да променяте стойности, като използвате опцията persistent.
mysql> SET PERSIST max_connections = 1000;
mysql> SET @@PERSIST.max_connections = 1000;
За по-стари версии използвайте:
mysql> SET GLOBAL max_connections = 1000;
$ vi /etc/mysql/my.cnf
SET GLOBAL max_connections = 1000;
Как да архивирам MySQL?
Има два начина за изпълнение на резервно копие на mysql.
За по-малки бази данни или по-малки селективни архиви можете да използвате командата mysqldump.
Архивиране на база данни с mysqldump (логическо архивиране):
mysqldump -uuser -p --databases db_name --routines --events --single-transaction | gzip > db_name_backup.sql.gz
xtrabackup, mariabackup (горещо двоично архивиране)
Предпочитаният метод е да използвате xtrabackup или mariabackup, външни инструменти за стартиране на горещи двоични архиви.
Oracle предлага горещо двоично архивиране в платената версия, наречена MySQL Enterprise Edition.
mariabackup --user=root --password=PASSWORD --backup --target-dir=/u01/backups/
Поточно архивиране към друг сървър
Стартирайте слушател на външния сървър на предпочитания порт (в този пример 1984)
nc -l 1984 | pigz -cd - | pv | xbstream -x -C /u01/backups
Изпълнете архивиране и прехвърлете към външен хост
innobackupex --user=root --password=PASSWORD --stream=xbstream /var/tmp | pigz | pv | nc external_host.com 1984
Копиране на потребителско разрешение
Често е необходимо да копирате потребителско разрешение и да ги прехвърлите на другите сървъри.
Препоръчителният начин да направите това е да използвате pt-show-grants.
pt-show-grants > /u01/backups
Как да възстановя MySQL?
Възстановяване на логическо архивиране
MySQLdump създава SQL файла, който може да се изпълни с командата източник.
За да запазите регистрационния файл на изпълнението, използвайте командата tee.
mysql> tee dump.log
mysql> source mysqldump.sql
Възстановяване на двоично архивиране (xtrabackup/mariabackup)
За да възстановите MySQL от двоичния архив, първо трябва да възстановите файловете и след това да приложите регистрационните файлове.
Можете да сравните този процес за възстановяване и възстановяване в Oracle.
xtrabackup --copy-back --target-dir=/var/lib/data
innobackupex --apply-log --use-memory=[values in MB or GB] /var/lib/data
Надяваме се, че тези съвети дават добър преглед на това как да изпълнявате основни административни задачи.