Выполнение [домашнего задания](https://github.com/netology-code/virt-homeworks/blob/master/06-db-03-mysql/README.md) 
по теме "6.3. MySQL".

## Q/A

### Задача 1

> Используя docker поднимите инстанс MySQL (версию 8). Данные БД сохраните в volume.
> 
> Изучите [бэкап БД](./dump/test_dump.sql) и восстановитесь из него.
> 
> Перейдите в управляющую консоль mysql внутри контейнера.
> 
> Используя команду \h получите список управляющих команд.
> 
> Найдите команду для выдачи статуса БД и приведите в ответе из ее вывода версию сервера БД.
> 
> Подключитесь к восстановленной БД и получите список таблиц из этой БД.
> 
> Приведите в ответе количество записей с price > 300.
> 
> В следующих заданиях мы будем продолжать работу с данным контейнером.

Для запуска контейнера с mysql будет использована конфигурация [docker-compose.yml](./docker-compose.yml).

Для восстановления из бэкапа нужно выполнить следующую команду:

```shell
docker-compose exec mysql bash -c "mysql -uroot -p123 -e 'CREATE DATABASE test_db'"
docker-compose exec mysql bash -c "mysql -uroot -p123 -Dtest_db < /opt/dump/test_dump.sql"
```

Затем нужно подключиться к БД и вывести статус:

```shell
docker-compose exec mysql mysql -uroot -p123
mysql> \status
--------------
mysql  Ver 8.0.15 for Linux on x86_64 (MySQL Community Server - GPL)
<...>
```

Подключение к восстановленной базе данных, вывод списка таблиц
и получение всех записей из таблицы `orders` с условием `price > 300`:

```shell
mysql> \u test_db
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;
+-------------------+
| Tables_in_test_db |
+-------------------+
| orders            |
+-------------------+
1 row in set (0.00 sec)

mysql> select count(id) from orders where orders.price > 300;
+-----------+
| count(id) |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)
```

### Задача 2

> Создайте пользователя `test` в БД c паролем `test-pass`, используя:
> - плагин авторизации mysql_native_password
> - срок истечения пароля - 180 дней
> - количество попыток авторизации - 3
> - максимальное количество запросов в час - 100
> - аттрибуты пользователя:
>     - Фамилия "Pretty"
>     - Имя "James"
>
> Предоставьте привилегии пользователю `test` на операции SELECT базы `test_db`.
> 
> Используя таблицу `INFORMATION_SCHEMA.USER_ATTRIBUTES` получите данные по пользователю `test` и приведите в ответе к задаче.

Запрос на создание пользователя:

```sql
CREATE USER 'test' 
  IDENTIFIED WITH mysql_native_password BY 'test-pass'
  WITH MAX_QUERIES_PER_HOUR 100
  PASSWORD EXPIRE INTERVAL 180 DAY
  FAILED_LOGIN_ATTEMPTS 3
  ATTRIBUTE '{"lname": "Pretty", "fname": "James"}';
```

Запрос на предоставление привилегий новому пользователю:

```sql
GRANT SELECT ON test_db.* TO 'test';
```

Запрос на получение данных о новом пользователе и его результат:

```shell
mysql> select * from INFORMATION_SCHEMA.USER_ATTRIBUTES where USER like 'test';
+------+------+---------------------------------------+
| USER | HOST | ATTRIBUTE                             |
+------+------+---------------------------------------+
| test | %    | {"fname": "James", "lname": "Pretty"} |
+------+------+---------------------------------------+
1 row in set (0.00 sec)
```

### Задача 3

> Установите профилирование `SET profiling = 1`.
> Изучите вывод профилирования команд `SHOW PROFILES;`.
> 
> Исследуйте, какой `engine` используется в таблице БД `test_db` и **приведите в ответе**.
> 
> Измените `engine` и **приведите время выполнения и запрос на изменения из профайлера в ответе**:
> - на `MyISAM`
> - на `InnoDB`

Внутри контейнера в утилите `mysql` выполним следующие запросы:

```shell
>mysql SET profiling = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

>mysql SHOW PROFILES;
+----------+------------+-------------------+
| Query_ID | Duration   | Query             |
+----------+------------+-------------------+
|        1 | 0.00148925 | SELECT DATABASE() |
|        2 | 0.00042175 | SELECT DATABASE() |
|        3 | 0.01061875 | show databases    |
|        4 | 0.00783050 | show tables       |
+----------+------------+-------------------+
4 rows in set, 1 warning (0.00 sec)
```

Вывод запроса `SHOW PROFILES` показывает, какие запросы были выполнены недавно на сервере к БД.
По умолчанию, хранится 15 последних запросов.

Для вывода движка таблицы необходимо использовать следующий запрос:

```sql
select engine from INFORMATION_SCHEMA.TABLES where table_name like 'orders';
+--------+
| ENGINE |
+--------+
| InnoDB |
+--------+
```

Для чистоты эксперимента, лучше всего будет выполнить запрос на `select` из таблицы, чтобы он попал в список профилировщика.
После этого нужно вывести скорость его выполнения:

```shell
mysql> select * from orders;
<...>
mysql> SHOW PROFILES;
+----------+------------+-----------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                       |
+----------+------------+-----------------------------------------------------------------------------+
| <...>    | <...>      | <...>                                                                       |
|        7 | 0.00249175 | select * from orders                                                        |
+----------+------------+-----------------------------------------------------------------------------+
```

Следующим шагом необходимо изменить `engine` таблицы, выполнить запрос на `select`
и снова вывести список из профилировщика:

```shell
mysql> alter table orders ENGINE='MYISAM';
Query OK, 5 rows affected (0.03 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from orders;
<...>

mysql> SHOW PROFILES;
+----------+------------+-----------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                       |
+----------+------------+-----------------------------------------------------------------------------+
| <...>    | <...>      | <...>                                                                       |
|        8 | 0.02865275 | alter table orders ENGINE='MYISAM'                                          |
|        9 | 0.00079400 | select * from orders                                                        |
+----------+------------+-----------------------------------------------------------------------------+
```

Затем нужно вернуть исходный движок таблицы:

```shell
alter table orders ENGINE='InnoDB';
Query OK, 5 rows affected (0.05 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> SHOW PROFILES;
+----------+------------+-----------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                       |
+----------+------------+-----------------------------------------------------------------------------+
| <...>    | <...>      | <...>                                                                       |
|       10 | 0.05557025 | alter table orders ENGINE='InnoDB'                                          |
+----------+------------+-----------------------------------------------------------------------------+
```

Таким образом, можно сделать два вывода:
1. Перестроение таблицы из `InnoDB` в `MYISAM` происходит быстрее, чем в другую сторону
2. Простейший запрос на `select` выполняется быстрее в таблице с `engine=MYISAM`, чем с `engine=InnoDB`

### Задача 4

> Изучите файл `my.cnf` в директории /etc/mysql.
> 
> Измените его согласно ТЗ (движок InnoDB):
> - Скорость IO важнее сохранности данных
> - Нужна компрессия таблиц для экономии места на диске
> - Размер буффера с незакомиченными транзакциями 1 Мб
> - Буффер кеширования 30% от ОЗУ
> - Размер файла логов операций 100 Мб
> 
> Приведите в ответе измененный файл `my.cnf`.

Файл `my.cnf` самостоятельно не когфигурирует mysql, но читает все конфиг-файлы из директории `/etc/mysql/conf.d`.
Таким образом, чтобы изменить конфигурацию сервера, достаточно создать новый файл, например, `/etc/mysql/conf.d/inno_db.cnf`.

Для выполнения задач из ТЗ, необходимо применить следующую конфигурацию:

- Скорость IO важнее сохранности данных: `innodb_flush_log_at_trx_commit = 2`
- Нужна компрессия таблиц для экономии места на диске: в данном случае это невозможно сконфигурировать,
  необходимо специально создавать или изменять таблицы, применяя `ROW_FORMAT=COMPRESSED`.
- Размер буффера с незакомиченными транзакциями 1 Мб: невозможно применить, так как минимальный размер конфига `innodb_log_file_size` - 4Мб.
- Буффер кеширования 30% от ОЗУ: `innodb_buffer_pool_size=5368709120`.
- Размер файла логов операций 100 Мб: `max_binlog_size=104857600`.

Конфигурация расположена в файле [inno_db.cnf](./inno_db.cnf).