MySQL - andyceo/documentation GitHub Wiki
sudo aptitude install mysql-server mysql-client
Можно установить из официального образа mysql, и с помощью Ansible-роли andyceo.docker: Ansible Docker config.
Ограничение на количество открываемых файлов накладывает операционная система. http://dev.mysql.com/doc/refman/5.1/en/table-cache.html
Системные переменные table_open_cache, max_connections, и max_tmp_tables определяют максимальное количество файлов, которые сервер может держать открытыми. При увеличении одного или нескольких этих значений, можно столкнуться с лимитом накладываемым операционной системой по количеству открытых файловых дескрипторов на один процесс. Большинство операционных систем позволяют увеличить лимит открытых файлов (open-files limit), однако способ существенно различается от системы к системе. Сверьтесь с документацией вашей операционной системы на предмет возможности увеличения лимита и способа это сделать.
Переменная table_open_cache соотносится с max_connections. К примеру, для 200 одновременных соединений вы должны установить размер кеша таблицы (table cache size), по меньшей мере, 200 × N, где N - максимальное количество таблиц к объединению (JOIN) в любом из исполняемых запросов. Также необходимо зарезервировать еще немного для дескрипторов временных таблиц и файлов.
А также http://www.hostcms.ru/documentation/server/mysql/
Файл настроек на конфигурацию с 2-мя Гб памяти. Помимо БД на сервере будут еще веб-сервер, фтп-сервер.
Содержимое файла /etc/mysql/my.cnf см. тут.
Раздел в разработке.
-
innodb_buffer_pool_size - это очень важный параметр для настройки InnoDB. Таблицы этого типа гораздо более чувствительны к размеру буфера, нежели MyISAM. MyISAM может нормально работать даже при дефолтном значении
buffer_size, в отличии от InnoDB, производительность которых будет заметно ниже при значенииinnodb_buffer_pool_sizeпо умолчанию и больших объемах данных. Также пул буферов InnoDB самостоятельно кэширует индексы и данные, так что не нужно оставлять место для кэша ОС. Обычно предполагается выделение 70 - 80% памяти для серверов, на которых ничего не запущено, кроме InnoDB. Некоторые правилаkey_bufferприменимы и в этом параметре: если у вас небольшие объемы данных и они не собираются стремительно увеличиваться, не завышайте значениеinnodb_buffer_pool_size, вы сможете найти свободной оперативной памяти лучшее применение. Вот формула в виде запроса, предложенная здесь, вычисляющая рекомендованное значение этого буфера:SELECT CONCAT(ROUND(KBS/POWER(1024,IF(Power1024<0,0, IF(Power1024>3,0,Power1024)))+0.49999),SUBSTR(' KMG',IF(Power1024<0,0, IF(Power1024>3,0,Power1024))+1,1)) recommended_innodb_buffer_pool_size FROM (SELECT SUM(data_length+index_length) KBS FROM information_schema.tables WHERE engine='InnoDB') A,(SELECT 2 Power1024) B; -
innodb_additional_mem_pool_size - этот параметр не имеет сильного влияния на производительность. По крайней мере в операционных системах с грамотным распределением памяти. Но вы можете установить значение этого параметра равным 20MB (иногда больше) и вы можете видеть сколько памяти выделяет InnoDB для различных нужд.
-
innodb_flush_log_at_trx_commit - Вам кажется, что InnoDB в сто раз медленнее MyISAM? Вероятно, вы забыли изменить значение этого параметра. Значение по умолчанию
1означает, что после каждой завершенной транзакции (или после изменения состояния транзакции) лог должен быть сброшен на диск. Это достаточно дорогая операция, особенно если у вас нет Battery backed up cache. Многие приложения, особенно те, в которых раньше использовался MyISAM будут хорошо работать при значении2, который означает, что не надо сбрасывать буфер на диск, а следует отправить его в кэш операционной системы. Лог по-прежнему будет сбрасываться на диск каждую секунду и максимум, что вы можете потерять - это 1-2 секунды записей. Значение0обеспечивает более высокую скорость, но и более низкую надежность. Есть вероятность потерять транзакции даже при падении mysql-сервера. При значении равном2единственная возможность потерять данные - это фатальный сбой операционной системы. -
innodb_flush_method = O_DSYNC (обычно - другой параметр. посоветовал Панов)
Ссылки:
Сделать дамп:
mysqldump -u root -p mydatabase > mydatabase.sql
Сделать консистентный дамп, если у вас в базе используется движок InnoDB и база большая, и одновременно запаковать дамп (больше информации):
mysqldump --single-transaction --quick -u root -p mydatabase | gzip > mydatabase.sql.gz
Сделать дамп только структуры таблиц, без данных:
mysqldump --no-data -u root -p mydatabase > mydatabase.sql
Создание дампа, в котором только первые 100 строк из каждой таблицы (пароль будет запрошен):
mysqldump --opt --where="1 LIMIT 100" -uroot -p DATABASE_NAME > DUMP.sql
Залить дамп:
mysql -u root -p mydatabase < dump.sql
Импорт дампа базы данных, упакованных в gzip (*.sql.gz):
gunzip < mydatabase.sql.gz | mysql -u root -p mydatabase
Вывести список таблиц, удовлетворяющих какому-либо критерию в базе mydatabase:
echo "show tables where Tables_in_mydatabase not like 'fias%' and Tables_in_mydatabase not like 'cache%';" | mysql -uroot -p hsbo
Сделать дамп всех таблиц в базе данных mydatabase, кроме fias% и cache%:
mysqldump -uroot -p"password" mydatabase `echo "show tables where Tables_in_mydatabase not like 'fias%' and Tables_in_mydatabase not like 'cache%';" | mysql -uroot -p"password" mydatabase | sed '/Tables_in/d'` > mydatabase.sql
Ссылки:
- Официальная документация mysqldump
- Утилита mysqldump и шпаргалка по параметрам
- http://dhampik.ru/blog/import-mysql-dump
- http://sngrl.ru/ssh-commands-list
- https://toster.ru/q/14127
- Создание урезанной базы данных в файл из MySQL
Чтобы разделить большой дамп по кускам на каждую таблицу при встрече CREATE TABLE, можно использовать такой скрипт:
cat dumpfile.sql | awk 'BEGIN {
output = "comments"; } $data ~ /^CREATE TABLE/ {
close(output);
output = substr($3,2,length($3)-2); }
{ print $data >> output }'
Если возникает ошибка вроде
awk: program limit exceeded: maximum number of fields size=32767
FILENAME="-" FNR=620 NR=620
то надо заменить awk на gawk.
Чтобы разделить большой дамп по кускам на каждую таблицу при встрече DROP TABLE IF EXISTS, можно использовать такой скрипт:
cat dumpfile.sql | gawk 'BEGIN {
output = "comments"; } $data ~ /^DROP TABLE IF EXISTS/ {
close(output);
output = substr($5,2,length($5)-3) ".sql"; }
{ print $data >> output }'
Источник: http://www.mindraven.com/blog/mysql/splitting-a-very-large-mysql-dump-file/
Есть еще несколько способов для разбиения файла на несколько. Допустим, что надо разделить огромный дамп на два. Первый кусок - от начала и до строки, где встречается DROP TABLE IF EXISTS trololo;, а другой кусок - от строки DROP TABLE IF EXISTS trololo; до конца файла. Номер строки DROP TABLE IF EXISTS trololo;` можно узнать так:
grep -n 'DROP TABLE IF EXISTS `trololo`;' dump.sql
где dump.sql - имя файла вашего большого дампа. Допустим, эта команда выдала что-то вроде:
17819:DROP TABLE IF EXISTS `trololo`;
Теперь используем команду split:
split -l 17818 dump.sql
Дамп dump.sql разделится на несколько файлов (не обязательно 2), в которые будут записаны ровно 17818 строк. Этот способ удобен, если искомая строка, на которой надо разбить файл, находится ближе к концу файла (номер строки больше половины количества строк), тогда он гарантированно разобьется на 2 файла и не побьет, например, транзакции в дампе.
Чтобы изменить что-то в большом файле (дампе БД), например, убрать премфиксы таблиц, можно использовать команду sed:
sed -i 's/hello/bye, bye!/g' dump.sql
Еще один способ, это доработать следующий скрипт:
#!/usr/bin/env python3
f = 'forum.2011_10_20.sql'
of = open('dump.sql', 'w')
flag = False
for ln, l in enumerate(open(f, 'rt')):
if flag or (l and l[:38] == 'DROP TABLE IF EXISTS `trololo`;'):
flag = True
of.write(l)
print('All done!')
of.close()
Однако, лично у меня этот скрипт вызвал ошибку:
andyceo@mycomp:~$ ./split.py
Traceback (most recent call last):
File "./split.py", line 9, in <module>
for ln, l in enumerate(open(f, 'rt')):
File "/usr/lib/python3.2/codecs.py", line 300, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x86 in position 1329: invalid start byte
В чем ее причина, я не знаю. Мой дамп был на 15 Гб.
PS: Также можно использовать split (http://philipp.cuntz.org/2011/01/linux-split-large-text-files.html, http://ru.wikipedia.org/wiki/Split)
Ссылки:
Создать нового MySQL пользователя и предоставить ему все права на некую базу данных очень просто:
GRANT ALL PRIVILEGES ON database.* TO 'user'@'localhost' IDENTIFIED BY 'password';
Если вы хотите предоставить пользователю возможность соединения не только с локального хоста, а вообще без всяких ограничений с любого IP-адреса, не забудьте в файле /etc/my.cnf закомментировать команду bind-address:
#bind-address = 127.0.0.1
и заменить в предыдущей команде 'localhost' на '%':
GRANT ALL PRIVILEGES ON database.* TO 'user'@'%' IDENTIFIED BY 'password';
Свой пароль можно поменять через:
SET PASSWORD = PASSWORD('пароль')
Пароль определенного пользователя можно поменять через:
SET PASSWORD FOR логин@localhost = PASSWORD('пароль');
SET PASSWORD FOR логин@"%" = PASSWORD('пароль');
тоже самое делают:
UPDATE mysql.user SET Password=PASSWORD('пароль') WHERE User='логин' AND Host='localhost';
FLUSH PRIVILEGES;
или
GRANT USAGE ON БД.* TO логин@localhost IDENTIFIED BY 'пароль';
или
mysqladmin -u логин password пароль
- http://ubuntu.flowconsult.at/en/mysql-set-change-reset-root-password/
- http://www.thegeekstuff.com/2009/07/change-reset-mysql-root-password-on-unix-linux/
- http://www.opennet.ru/tips/info/606.shtml
В случае, если забыт старый root-пароль или его сбросили на неизвестный, и при этом MySQL работает в docker-контейнере, нужно запустить контейнер со следующей командой:
command: --skip-grant-tables --skip-networking
затем зайти внутрь контейнера с помощью exec, вызвать клиент командной строки mysql и выполнить там:
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass';
FLUSH PRIVILEGES;
(в случае необходимости надо заменить localhost на % или тот хост который нужен, а MyNewPass - на новый пароль) и перезапустить контейнер в нормальном режиме, без опций --skip-grant-tables --skip-networking. После этого можно будет зайти в MySQL под пользователем root с новым паролем.
Ссылки:
- B.5.3.2 How to Reset the Root Password, искать секцию B.5.3.2.3 Resetting the Root Password: Generic Instructions
Показать список текущих соединений и выполняемых запросов:
SHOW PROCESSLIST;
Убить соединение (и запрос, выполняемый в нем):
KILL **Id**
где Id - это id соединения из SHOW PROCESSLIST
Убить только запрос внутри соединения, само соединение останется в живых:
KILL QUERY **Id**
где Id - это id соединения из SHOW PROCESSLIST
-
Сначала надо выключить mysql на старом сервере:
sudo /etc/init.d/mysql stop -
Затем всю папку
/var/lib/mysqlположить в один ахив tar:cd /var/lib sudo tar -cf mysql.tar mysql -
Залить на новый сервер этот архив
-
Распаковать:
sudo tar -xf mysql.tar -
Переместить получившуюся директорию
mysqlв/var/lib -
Поставить на нее следующие права и владельца:
-
TODO:Поправить права и владельцев директорий и папок:
sudo find /var/www/ -type f -exec chmod 644 {} \; sudo find /var/www/ -type d -exec chmod 755 {} \; sudo chown www-data:www-data -R /var/www/ -
поправить пароль для пользователя
debian-sysв файле/etc/mysql/debian.cnfна тот, что был на старом сервере. Или использовать такой метод:# killall mysqld # mysqld_safe --skip-grant-table ^Z # bg # mysql -u root > UPDATE mysql.user SET Password = PASSWORD( 'новый пароль' ) WHERE user.Host = 'localhost' AND user.User = 'debian-sys-maint'; > exit # fg ^C # /etc/init.d/mysql start
Если нужно обновить MySQL, то есть два способа: через mysql_upgrade и путем создания дампов со старой базы и импорта их на новую. Версия 5.7.17 умеет апгрейдить "на лету". В случае, если вы запустили докер-контейнер над папкой с данными от MySQL старой версии, можно сделать следующее:
sudo docker exec -ti mysql-container-name mysql_upgrade -u root -p"ROOT_PASSWORD"
Затем нужно обязательно перезапустить контейнер с MySQL, иначе при попытке дампа может быть такая ошиюка:
mysqldump: Couldn't execute 'SHOW VARIABLES LIKE 'gtid\_mode'': Native table 'performance_schema'.'session_variables' has the wrong structure (1682)
Перезапуск корректно делать такой командой:
sudo docker exec -ti mysql-container-name mysqladmin -u root -p"ROOT_PASSWORD" shutdown
ROOT_PASSWORD можно не указывать, тогда MySQL интерактивно спросит его.
Что получилось? Запуск
sudo aptitude dist-upgrade
попытался обновить мне mysql-server, но:
invoke-rc.d: initscript mysql, action "start" failed.
dpkg: error processing mysql-server-5.1 (--configure):
subprocess post-installation script returned error exit status 1
dpkg: dependency problems prevent configuration of mysql-server:
mysql-server depends on mysql-server-5.1; however:
Package mysql-server-5.1 is not configured yet.
dpkg: error processing mysql-server (--configure):
dependency problems - leaving unconfigured
Errors were encountered while processing:
mysql-server-5.1
mysql-server
Это произошло потому, что нужно было избавиться от пакета mysql-common через purge (и все зависимые от него пакеты), а затем с чистого листа установить mysql-server:
sudo aptitude purge mysql-common
Если спросит про другие пакеты, которые тоже надо удалить, соглашайтесь!!!
ВНИМАНИЕ! Это все мне также удалило proftpd, и proftpd-mysql (надо ставить заново).
Также перестал работать cacti и версия mysql-server отличается от версии mysql-client.
ВНИМАНИЕ! Файл настроек /etc/my.cnf обнулился (ведь мы сделали purge, поэтому нужен бэкап настроек). Однако не забыть убрать упоминание о BerkeleyDB!! а то будет ошибка.
Источники:
- dpkg: error processing mysql-server (--configure)
- Mysql fails to install after "aptitude purge mysql-server --purge-unused"
- Принципы работы СУБД. MVCC
- Использование EXPLAIN. Улучшение запросов
- maatkit - утилита анализа логов mysql от percona
- Trees and Other Hierarchies in MySQL
- Storing a Directed Graph in SQL
- MySQL storing undirected graph edges efficiently
- Models for hierarchical data
Полезный флаг в консоли MySQL, который переворачивает строки со столбцами (удобно смотреть, если строка длинная):
mysql> select * from users_field_data;
+-----+----------+--------------------+--------------------------+------+---------------------------------------------------------+----------------------------+---------------+--------+------------+------------+------------+------------+----------------------------+------------------+
| uid | langcode | preferred_langcode | preferred_admin_langcode | name | pass | mail | timezone | status | created | changed | access | login | init | default_langcode |
+-----+----------+--------------------+--------------------------+------+---------------------------------------------------------+----------------------------+---------------+--------+------------+------------+------------+------------+----------------------------+------------------+
| 0 | ru | ru | NULL | | NULL | NULL | | 0 | 1451669332 | 1451669332 | 0 | 0 | NULL | 1 |
| 1 | ru | ru | NULL | root | $S$EhBCsTciNdQFHxLPgwfFIXY.7GLGjyzjiiX.JXJ6DM1ZO.rEkFzm | [email protected] | Europe/Moscow | 1 | 1451669332 | 1451818176 | 1452261434 | 1452251276 | [email protected] | 1 |
+-----+----------+--------------------+--------------------------+------+---------------------------------------------------------+----------------------------+---------------+--------+------------+------------+------------+------------+----------------------------+------------------+
2 rows in set (0.00 sec)
Попробуем:
mysql> select * from users_field_data\G
*************************** 1. row ***************************
uid: 0
langcode: ru
preferred_langcode: ru
preferred_admin_langcode: NULL
name:
pass: NULL
mail: NULL
timezone:
status: 0
created: 1451669332
changed: 1451669332
access: 0
login: 0
init: NULL
default_langcode: 1
*************************** 2. row ***************************
uid: 1
langcode: ru
preferred_langcode: ru
preferred_admin_langcode: NULL
name: root
pass: $S$EhBCsTciNdQFHxLPgwfFIXY.7GLGjyzjiiX.JXJ6DM1ZO.rEkFzm
mail: [email protected]
timezone: Europe/Moscow
status: 1
created: 1451669332
changed: 1451818176
access: 1452261434
login: 1452251276
init: [email protected]
default_langcode: 1
2 rows in set (0.00 sec)
т.е. \G вместо ;.