# MySQL

Описан процесс установки MySQL и настройка базовой репликации мастер -> слейв

- [MySQL](#mysql)
  - [Установка сервера MySQL 8 в Debian 12](#установка-сервера-mysql-8-в-debian-12)
  - [Создание тестовой БД и наполнение данными](#создание-тестовой-бд-и-наполнение-данными)
    - [Подключение к СУБД](#подключение-к-субд)
    - [Создание базы данных](#создание-базы-данных)
    - [Переключение на созданную базу данных](#переключение-на-созданную-базу-данных)
    - [Создание таблицы в базе данных](#создание-таблицы-в-базе-данных)
    - [Добавление записей в таблицу](#добавление-записей-в-таблицу)
    - [Выборка из таблицы](#выборка-из-таблицы)
  - [Репликация](#репликация)
    - [Пользователь для выполнения задач репликации](#пользователь-для-выполнения-задач-репликации)
    - [Настройка мастера для репликации](#настройка-мастера-для-репликации)
    - [Дамп БД](#дамп-бд)
    - [Настройка слейва](#настройка-слейва)
    - [Настройка репликации](#настройка-репликации)
    - [Запуск воспроизведения журнала ретрансляции, и проверка статуса репликации](#запуск-воспроизведения-журнала-ретрансляции-и-проверка-статуса-репликации)
    - [Проверка репликации](#проверка-репликации)

## Установка сервера MySQL 8 в Debian 12

На сайте [MySQL в разделе Community](https://dev.mysql.com/downloads/mysql/) выбрать необходимую версию (8.4.3 LTS на момент написания заметки), в качестве ОС выбрать Debian.
После выбора ОС появится предложение выполнить установку используя репозиторий APT, нажимаем ссылку, будет предложено скачать пакет для настройки репозитория (mysql-apt-config_0.8.33-1_all.deb на момент написания заметки). Далее в консоли по документации - https://dev.mysql.com/doc/refman/8.4/en/linux-installation-apt-repo.html

```shell
su -

wget https://dev.mysql.com/get/mysql-apt-config_0.8.33-1_all.deb
apt instlall -y ./mysql-apt-config_0.8.33-1_all.deb
```

В появившемся окне выбрать - `Ok`

```shell
dpkg-reconfigure mysql-apt-config

apt update
apt install mysql-server
```

Можно также выполнить настройки безопасности

```shell
mysql_secure_installation
```

## Создание тестовой БД и наполнение данными

### Подключение к СУБД

```shell
mysql -u root -p
```

### Создание базы данных

```shell
CREATE DATABASE IF NOT EXISTS sape_test_db;
```

По ошибке была создана БД с именем - `sape_test_db.db`

При её удалении полачал ошибку

```shell
mysql> drop database 'sape_test_db.db';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''sape_test_db.db'' at line 1
```

Поиск причин привёл - <https://stackoverflow.com/questions/16135987/error-on-drop-default-database-error>

при использовании в названии зарезервированных слов, следует заключать имя БД в косые ковычки `

```shell
mysql> drop database `sape_test_db.db`;
Query OK, 0 rows affected (0,17 sec)
```

### Переключение на созданную базу данных

```shell
USE sape_test_db;
```

### Создание таблицы в базе данных

таблица будет содержать три столбца: id, name, surname, address. Первичным ключом будет id. В качестве движка явно укажем InnoDB.

```shell
CREATE TABLE admin_table
( id int NOT NULL AUTO_INCREMENT,
name char(20) NOT NULL,
surname char(20) NOT NULL,
city char(20) NULL,
PRIMARY KEY (id) )
ENGINE=InnoDB;
```

для удаления таблицы

```shell
DROP TABLE admin_table;
```

### Добавление записей в таблицу

```shell
INSERT admin_table(name, surname, city) VALUES ('Andrei', 'Ahmadulin', 'Ekaterinburg');
INSERT admin_table(name, surname, city) VALUES ('Kit', 'Root', 'Georgia');
INSERT admin_table(name, surname, city) VALUES ('Ilya', 'Paramonov', 'Moscow');
INSERT admin_table(name, surname, city) VALUES ('Andrei', 'Zharkov', 'Moscow');
INSERT admin_table(name, surname, city) VALUES ('Artem', 'Dolgiy', 'Zelenograd');
```

### Выборка из таблицы

```shell
SELECT * FROM admin_table;
```

## Репликация

### Пользователь для выполнения задач репликации

Будет создан пользователь `repl_user` с паролем `repl_passwd`

```shell
mysql -u root -p
```

```shell
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'repl_passwd';
```

Если возникнет ошибка - `ERROR 1819 (HY000): Your password does not satisfy the current policy requirements` - <https://stackoverflow.com/questions/43094726/your-password-does-not-satisfy-the-current-policy-requirements>

кратко - достаточно изменить политику паролей

```shell
mysql> SHOW VARIABLES LIKE 'validate_password%';
+-------------------------------------------------+--------+
| Variable_name                                   | Value  |
+-------------------------------------------------+--------+
| validate_password.changed_characters_percentage | 0      |
| validate_password.check_user_name               | ON     |
| validate_password.dictionary_file               |        |
| validate_password.length                        | 8      |
| validate_password.mixed_case_count              | 1      |
| validate_password.number_count                  | 1      |
| validate_password.policy                        | MEDIUM |
| validate_password.special_char_count            | 1      |
+-------------------------------------------------+--------+
8 rows in set (0,03 sec)

mysql> SET GLOBAL validate_password.policy = LOW;
Query OK, 0 rows affected (0,00 sec)

mysql> 
```

Назначение привилегий для пользователя

```shell
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
```

### Настройка мастера для репликации

В файл `/etc/mysql/my.cnf` (или в `/etc/mysql/mysql.conf.d/mysqld.cnf`, в зависимости от настроек) в секции `[mysqld]` необходимо добавить следующие параметры:

```shell
server_id = 1 # назначает серверу уникальный целочисленный идентификатор
log_bin = mysql-bin # включает двоичный журнал и указывает его расположение
```

После изменения конфигурации необходимо перезагрузить СУБД

```shell
systemctl restart mysql.service
```

Стоит убедиться, что двоичный журнал включен

```shell
SHOW BINARY LOG STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 |      158 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0,00 sec)
```

В более ранних версиях используется команда - `SHOW MASTER STATUS;`

- <https://habr.com/ru/articles/532216/>
- <https://www.k-max.name/linux/replikaciya-mysql-master-slave/>

### Дамп БД

Для того, чтобы начать репликацию данных, необходимо “подтянуть” слейв до состояния мастера. Для этого, нужно временно заблокировать сам мастер, чтобы сделать слепок актуальных данных.

```shell
FLUSH TABLES WITH READ LOCK;
```

Далее, с помощью mysqldump сделать экспорт данных из базы.

```shell
mysqldump -u root -p sape_test_db > sape_test_db.db
```

После этого, необходимо еще раз выполнить команду `SHOW BINARY LOG STATUS;`, и запомнить или записать значения File и Position. Это, так называемые координаты двоичного журнала. Именно от них далее будет указано стартовать слейву.

Теперь мастер можно разблокировать.

```shell
UNLOCK TABLES;
```

Мастер настроен, и готов реплицироваться на другие сервера.

### Настройка слейва

В первую очередь на слейв необходимо загрузить дамп, полученный с мастера

```shell
root@master:~# scp sape_test_db.db slave:/root
sape_test_db.db                                                                                                       100% 2169     2.5MB/s   00:00    
root@master:~# 
```

```shell
CREATE DATABASE `sape_test_db`;
```

```shell
mysql -u root -p sape_test_db < /root/sape_test_db.db
```

Изменить конфигурацию слейва `/etc/mysql/my.cnf` (или в `/etc/mysql/mysql.conf.d/mysqld.cnf`, в зависимости от настроек) в секции `[mysqld]`

```shell
log_bin = mysql-bin  # указываем слейву вести собственный двоичный журнал
server_id = 2  # указываем идентификатор сервера
relay-log = /var/lib/mysql/mysql-relay-bin # указываем расположение журнала ретрансляции
relay-log-index = /var/lib/mysql/mysql-relay-bin.index  # этот файл служит перечнем всех имеющихся журналов ретрансляции
read_only = 1  # переводим слейв в режим “только чтение”
```

После изменения конфигурации необходимо перезагрузить службу

```shell
systemctl restart mysql.service
```

### Настройка репликации

Необходимо указать слейву, какой сервер будет являться для него мастером, и откуда начинать реплицировать данные. Вместо `MASTER_LOG_FILE` и `MASTER_LOG_POS` необходимо подставить значения, полученные из `SHOW BINARY LOG STATUS;` на мастере. Эти параметры вместе называются координатами двоичного журнала.

Адрес мастера указан в `hosts`, поэтому достаточно указать его имя

```shell
CHANGE REPLICATION SOURCE TO SOURCE_HOST='master', SOURCE_USER='repl_user', SOURCE_PASSWORD='repl_passwd', SOURCE_LOG_FILE='mysql-bin.000002', SOURCE_LOG_POS=158;
```

В более ранних версиях используется команда - `CHANGE MASTER TO...`

### Запуск воспроизведения журнала ретрансляции, и проверка статуса репликации

```shell
start replica;
```

```shell
mysql> show replica status\G
*************************** 1. row ***************************
             Replica_IO_State: Waiting for source to send event
                  Source_Host: master
                  Source_User: repl_user
                  Source_Port: 3306
                Connect_Retry: 60
              Source_Log_File: mysql-bin.000002
          Read_Source_Log_Pos: 158
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 328
        Relay_Source_Log_File: mysql-bin.000002
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Source_Log_Pos: 158
              Relay_Log_Space: 539
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Source_SSL_Allowed: No
           Source_SSL_CA_File: 
           Source_SSL_CA_Path: 
              Source_SSL_Cert: 
            Source_SSL_Cipher: 
               Source_SSL_Key: 
        Seconds_Behind_Source: 0
Source_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Source_Server_Id: 1
                  Source_UUID: 1337616f-ad64-11ef-ba97-bc2411fcdf96
             Source_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
    Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Source_Retry_Count: 10
                  Source_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Source_SSL_Crl: 
           Source_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Source_TLS_Version: 
       Source_public_key_path: 
        Get_Source_public_key: 0
            Network_Namespace: 
1 row in set (0,00 sec)
```

Если все прошло успешно, ваш статус должен иметь аналогичный вид. Ключевые параметры здесь:

`Replica_IO_State`, `Replica_SQL_Running_State` — состояние IO потока, принимающего двоичный журнал с мастера, и состояние потока, применяющего журнал ретрансляции соотвественно. Только наличие обоих потоков свидетельствует об успешном процессе репликации.  
`Read_Source_Log_Pos` — последняя позиция, прочитанная из журнала мастера.  
`Relay_Source_Log_File` — текущий файл журнала мастера.  
`Seconds_Behind_Source` — отставание слейва от мастера, в секундах.  
`Last_IO_Error`, `Last_SQL_Error` — ошибки репликации, если они есть.  

### Проверка репликации

На мастере добавить данные и убедиться, что они появились на слейве

```shell
mysql -u root -p
use sape_test_db;

INSERT admin_table(name, surname, city) VALUES ('Nikita', 'Samoilov', 'Sankt-Petersburg');
```

```shell
mysql> select * from admin_table;
+----+--------+-----------+------------------+
| id | name   | surname   | city             |
+----+--------+-----------+------------------+
|  1 | Andrei | Ahmadulin | Ekaterinburg     |
|  2 | Kit    | Root      | Georgia          |
|  3 | Ilya   | Paramonov | Moscow           |
|  4 | Andrei | Zharkov   | Moscow           |
|  5 | Artem  | Dolgiy    | Zelenograd       |
|  6 | Nikita | Samoilov  | Sankt-Petersburg |
+----+--------+-----------+------------------+
6 rows in set (0,00 sec)
```

Проверить данные на слейве

```shell
mysql> select * from admin_table;
+----+--------+-----------+------------------+
| id | name   | surname   | city             |
+----+--------+-----------+------------------+
|  1 | Andrei | Ahmadulin | Ekaterinburg     |
|  2 | Kit    | Root      | Georgia          |
|  3 | Ilya   | Paramonov | Moscow           |
|  4 | Andrei | Zharkov   | Moscow           |
|  5 | Artem  | Dolgiy    | Zelenograd       |
|  6 | Nikita | Samoilov  | Sankt-Petersburg |
+----+--------+-----------+------------------+
6 rows in set (0,00 sec)
```

Материалы для ознакомления

- <https://habr.com/ru/companies/oleg-bunin/articles/309326/>
- <https://habr.com/ru/articles/56702/>
- <https://habr.com/ru/companies/otus/articles/600153/>
- <https://habr.com/ru/companies/selectel/articles/708434/>

ещё

- <https://habr.com/ru/articles/532216/>
- <https://timeweb.cloud/tutorials/mysql/kak-nastroit-replikatsiyu-v-mysql>
- <https://www.k-max.name/linux/replikaciya-mysql-master-slave/>
