Wiki
Clone wikiconfigs / db / mysql
MySQL
Тюнинг
Ничего сам не правит, просто отображает рекомендуемые настройки кеширования и прочих радостей. Неплохо развивается, must have
Перловый тюнер
Создание БД
Лучше сразу указывать кодировку:
#!SQL CREATE DATABASE `my_db` CHARACTER SET utf8 COLLATE utf8_general_ci;
Пользователи
Создание пользователя со всеми правами
#!SQL GRANT ALL PRIVILEGES ON *.* TO root@'%' identified by "PASSWORD";
Создание пользователя с правами на таблицы определённого префикса
#!SQL GRANT ALL PRIVILEGES ON `vr\_%`.* TO 'vr'@'localhost';
Восстановление пароля root (или любого пользователя БД)
Останавливаем mysql:
#!bash
sudo /etc/mysqld stop
Запускаем обратно, но со спецфлагом (без привилегий):
#!bash sudo /etc/mysqld --skip-gran-tables&
Логинимся в СУБД от имени root:
#!bash
mysql -u root
Обновляем поле с паролем для пользователя root(либо любого другого) в системной таблице user. Новый пароль вписываем вместо newpass:
#!sql UPDATE mysql.user SET Password=PASSWORD('newpass') WHERE User='root';
Обновляем привилегии:
#!sql FLUSH PRIVILEGES;
Выходим из mysql: exit; Рестарт mysql:
#!bash
/etc/mysqld restart
Работа с запросами
поглядеть все текущие запросы SHOW FULL PROCESSLIST;
убить конкретный запрос по ид KILL $queryID;
всяческие выборки по процесслисту возможны из системных таблиц:
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE time >20 and COMMAND !='Sleep' order by time\G
General Log
Текущие настройки:
show variables where Variable_name in ('version', 'log', 'general_log', 'general_log_file', 'log_output');
SET GLOBAL general_log_file='/var/log/mysql/general.log'; SET GLOBAL general_log=ON;
Включать в general log в основном конфиге - плохая идея. Желательно его включать только на время дебага и как можно быстрее отключать (
SET GLOBAL general_log=OFF;
).
Slow Log
Настройки:
mysql> show variables where Variable_name like ('slow%');
Включение/выключение
SET GLOBAL slow_query_log = OFF; SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 10;
Самые большие таблицы
SELECT table_schema,TABLE_NAME, SUM( data_length + index_length) / 1024 / 1024 "Data Base Size in MB" FROM information_schema.TABLES GROUP BY table_name,table_schema ORDER BY 3; SELECT table_schema, SUM( data_length + index_length) / 1024 / 1024 "Data Base Size in MB" FROM information_schema.TABLES GROUP BY table_schema ORDER BY 2;
Репликация
Настройки сервера для запуска репликации
server-id = 1 log-bin = /var/lib/mysql/mysql-bin replicate-do-db = testdb # базы подлежащие репикации max_binlog_size = 100M # размер одного файла бинлогов binlog_ignore_db = test # не реплицировать указанные базы binlog_ignore_db = mysql binlog_ignore_db = performance_schema binlog_ignore_db = information_schema expire_logs_days = 3 # затирать бинлоги старее 3 дней
Создание ползователя для репликации
grant replication slave, replication client on *.* to replication@"%" identified by "password";
статус слейва:
show slave status\G *************************** 1. row *************************** Slave_IO_State: Какойнибудь хороший/плохой статус Master_Host: 192.168.0.1 Master_User: replication Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.002946 Read_Master_Log_Pos: 6231609 Relay_Log_File: mysqld-relay-bin.001922 Relay_Log_Pos: 4312353 Relay_Master_Log_File: mysql-bin.002946 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: exclude.%tmp Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 6231609 Relay_Log_Space: 6231953 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 3012 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: 1 row in set (0.00 sec)
Seconds_Behind_Master: 3012
- на сколько секунд отстал от мастераSlave_IO_State:
- статус, должен быть Waiting for master to send event
Last_Error:
- если чтото не так - тут будет ошибкаLast_SQL_Error:
- ну или тут, но обычно и там и там одно и тоже.
Slave_IO_Running: Yes Slave_SQL_Running: Yes
Если чтото не так - в первую очередь пытаемся перезагрузить слейв командами:
STOP SLAVE; START SLAVE;
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;
Еще полезные команды по репликации
Показывает статус мастера (если не запущен ничего не выдаст):
SHOW MASTER STATUS;
SHOW SLAVE HOSTS;
SHOW BINARY LOGS;
PURGE BINARY LOGS TO 'mysql-bin.000030'; PURGE BINARY LOGS BEFORE NOW() - INTERVAL 30 DAY;
slave stop
)
CHANGE MASTER TO MASTER_HOST = '192.168.0.1', MASTER_USER = 'replication', MASTER_PASSWORD = 'xxxxxxxx', MASTER_CONNECT_RETRY = 30, MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 385, MASTER_HEARTBEAT_PERIOD = 10 ;
Duplicate entry
(1062) в конфиг сервера можно добавить директиву и перезагрузить сервис (не рекомендуется, но как временное решение может быть полезно)
[mysqld] slave-skip-errors=1062
Прочее:
RESET SLAVE; FLUSH LOGS; SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]; CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD = 10;
Репликация в MariaDB
Мария в 10 версии умеет мультимастерную репликацию. Есть некоторые ограничения (например 64 мастера максимум), но в целом довольно мощно.
Для переключения между инстансами репликации используем команды
set @@default_master_connection='master1'; CHANGE MASTER TO MASTER_HOST = '1.1.1.1', MASTER_USER = 'replication', MASTER_PASSWORD = 'replication', MASTER_CONNECT_RETRY = 30, MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 120; set @@default_master_connection='master2'; CHANGE MASTER TO MASTER_HOST = '2.2.2.2', MASTER_USER = 'replication', MASTER_PASSWORD = 'replication', MASTER_CONNECT_RETRY = 30, MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 120;
Естественно, имена могу быть любыми
Для вывода статуса всех слейвов используем команду:
show all slaves status\G
Еще полезности по репликации в марии
RESET SLAVE ['connection_name']
- сбросить все параметры подключения к мастеру
SHOW SLAVE ['connection_name'] STATUS
- показать статус конкретного подключения
SHOW ALL SLAVES STATUS
- показать статус всех подклчений
START SLAVE ['connection_name']
- запустить указанное подключение
START ALL SLAVES
- запустить все подключения
STOP SLAVE ['connection_name']
- остановить указанное подключение
STOP ALL SLAVES
- остановить все подключения
Здесь можно почитать подробнее
Бекап
Создание
mysqldump --all-database -pPASSWORD | gzip > dump.sql.gz
Бекапаются все базы и таблицы, включая системные. Лучше не восстанавливать целиком
Восстановление
zcat dump.sql.gz | mysql -pPASSWORD
Нарезка
Для разрезания файла бекапа на базы используем скрипт
#!/usr/bin/perl -w # # splitmysqldump - split mysqldump file into per-database dump files. use strict; use warnings; my $dbfile; my $dbname = q{}; my $header = q{}; while (<>) { # Beginning of a new database section: # close currently open file and start a new one if (m/-- Current Database\: \`([\.\-\w]+)\`/) { if (defined $dbfile && tell $dbfile != -1) { close $dbfile or die "Could not close file!" } $dbname = $1; open $dbfile, ">>", "$1_dump.sql" or die "Could not create file!"; print $dbfile $header; print "Writing file $1_dump.sql ...\n"; } if (defined $dbfile && tell $dbfile != -1) { print $dbfile $_; } # Catch dump file header in the beginning # to be printed to each separate dump file. if (! $dbname) { $header .= $_; } } close $dbfile or die "Could not close file!"
Для нарезания базы на таблицы используем скрипт
#!/bin/sh #SPLIT DUMP FILE INTO INDIVIDUAL TABLE DUMPS TARGET_DIR="." DUMP_FILE=$1 TABLE_COUNT=0 if [ $# = 0 ]; then echo "Usage: MyDumpSplitter.sh DUMP-FILE-NAME -- Extract all tables as a separate file from dump." echo " MyDumpSplitter.sh DUMP-FILE-NAME TABLE-NAME -- Extract single table from dump." echo " MyDumpSplitter.sh DUMP-FILE-NAME -S TABLE-NAME-REGEXP -- Extract tables from dump for specified regular expression." exit; elif [ $# = 1 ]; then #Loop for each tablename found in provided dumpfile for tablename in $(grep "Table structure for table " $1 | awk -F"\`" {'print $2'}) do #Extract table specific dump to tablename.sql sed -n "/^-- Table structure for table \`$tablename\`/,/^-- Table structure for table/p" $1 > $TARGET_DIR/$tablename.sql TABLE_COUNT=$((TABLE_COUNT+1)) done; elif [ $# = 2 ]; then for tablename in $(grep -E "Table structure for table \`$2\`" $1| awk -F"\`" {'print $2'}) do echo "Extracting $tablename..." #Extract table specific dump to tablename.sql sed -n "/^-- Table structure for table \`$tablename\`/,/^-- Table structure for table/p" $1 > $TARGET_DIR/$tablename.sql TABLE_COUNT=$((TABLE_COUNT+1)) done; elif [ $# = 3 ]; then if [ $2 = "-S" ]; then for tablename in $(grep -E "Table structure for table \`$3" $1| awk -F"\`" {'print $2'}) do echo "Extracting $tablename..." #Extract table specific dump to tablename.sql sed -n "/^-- Table structure for table \`$tablename\`/,/^-- Table structure for table/p" $1 > $TARGET_DIR/$tablename.sql TABLE_COUNT=$((TABLE_COUNT+1)) done; else echo "Please provide proper parameters."; fi fi #Summary echo "$TABLE_COUNT Table extracted from $DUMP_FILE at $TARGET_DIR"
Updated