MySQLemoji, MySQL и кодировка UTF-8

Давно уже, многие годы, знал о проблеме, что комментарии в этом блоге с эмоджами не сохраняются, как и статьи, потому что MySQL ругался чем-то вроде Incorrect string value: '\xF0\x9F\x87\xB2...' for column 'text' at row 1 и записи не сохранял. Но исправить эту штуку было просто недосуг, комментируют здесь не то, чтобы сильно часто, да и то чаще боты со спамом. А вот в новой версии движка блога, которая уже фактически запущена, это было запланировано к исправлению 😁

Когда переносил блог на новый сервер, то установил там восьмую версию мускула и проверил, сохраняет или нет. Вдруг разработчики базы данных давно уже исправили этот incorrect string value, я ведь не один такой на планете с эмоджами, нас десятки и сотни тысяч, уверен, если не миллионы. Но результат не поменялся, та же ошибка. Не прокатило, штош...

DockerПодключение к локальному MySQL из Docker-контейнера

Если возникнет необходимость подключиться из докер-контейнера к серверу MySQL, установленному на хост-машине, то сделать это можно следующим образом. Для начала определяем IP-адрес хоста:

1
ip addr show

Выбираем из появившейся кучи букв и цифр искомый адрес. У меня получилось, к примеру, 192.168.1.176. К нему и будем подключаться из докера. Адрес желательно иметь фиксированный, чтобы не менять его в настройках подключения от перезагрузки к перезагрузке, у себя привязку IP к MAC-адресу сделал сто лет в настройках роутера.

Далее поднастроим MySQL. Для начала в /etc/mysql/my.cnf находим и редактируем директиву bind-address, чтобы сервер БД прослушивал все адреса, а не только localhost:

1
2
# /etc/mysql/my.cnf
bind-address = 0.0.0.0

И создадим базу данных и пользователя, который будет подключаться из докера:

1
2
3
4
5
6
CREATE DATABASE pupkin_db;
CREATE USER pupkin IDENTIFIED BY 'secret_password';
GRANT ALL PRIVILEGES ON pupkin_db.* TO pupkin;

-- сразу обновим права доступа
FLUSH PRIVILEGES;

Готово 🙂

А если используется MySQL 8, в котором по умолчанию используется метод аутентификации caching_sha2_password и приложение такой не поддерживает, например не самые свежайшие PHP, то чтобы не наблюдать ошибки вроде SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client необходимо сменить метод аутентификации на более старый:

1
ALTER USER pupkin IDENTIFIED WITH mysql_native_password BY 'secret_password';

MySQLПакетное обновление или batch update

Иногда возникает потребность обновить много записей в базе данных, например 3000, 7000 или 25000 штук. Видел даже веб-формы с таким количеством полей, хоть это и полное безумие :) Можно, конечно, обновить эти записи поштучно, но бомбардировать сервер базы данных запросами - плохая идея. Желательно сделать это за раз. И сделать это возможно следующим образом:

1
2
3
INSERT INTO table (`id`, `x`, `y`) VALUES
  (1, 2, 3), (4, 5, 6), (7, 8, 9)
  ON DUPLICATE KEY UPDATE `x` = VALUES(`x`), `y` = VALUES(`y`);

P.S.: Однако, как подсказывают в комментариях, есть нюанс. В случае этого самого ON DUPLICATE KEY UPDATE автоинкрементное поле для таблиц InnoDB всё равно увеличится, будто была вставка в таблицу.

LinuxЗапуск MySQL-сервера после падений

Так уж вышло, что на одном из подконтрольных мне серверов, то ли от нехватки памяти, то ли от всплесков нагрузки, то ли от того и другого сразу, регулярно падает сервер БД MySQL. Где-то раз в неделю или две. Особенно нехорошо, когда владелец сайтов, размещённых на этом сервере, звонит в связи с этим рано утром или ночью, так что доктор прописал процесс подъема БД автоматизировать.

Первое решение нарисовалось при переписке с известным крутокодером. И имя этого решения monit, однако картина с ним принципиально не поменялась, периодические падения не закончились. Может быть чего-то в доках не дочитал, может руками кривыми конфиги редактировал, но не срослось. Причём в тестовых остановках мускула монит отрабатывал отлично, а в реальности, видимо, не всегда.

MySQLMySQL Query Cache

Оставляю себе в качестве шпаргалки.

Необходимые запросы к БД для проверки работоспособности и просмотра состояния дел.

1
2
3
SHOW variables LIKE 'have_query_cache';
SHOW variables LIKE 'query%';
SHOW status LIKE 'Qcache%';