目录
使用 Docker 来管理 MySQL、Redis 等各种中间件是十分方便的,无论是生产环境,还是开发环境都非常方便。今天来说一下我用 Docker 来管理 MySQL 时遇到的一个小坑。
在 Docker 下部署 MySQL
在 Docker 下部署 MySQL 是很方便的,通过几条命令就可以轻轻松松的下载镜像并完成安装部署。
首先,拉取MySQL镜像:
% docker pull mysql:latest
latest: Pulling from library/mysql
a076a628af6f: Already exists
f6c208f3f991: Pull complete
88a9455a9165: Pull complete
406c9b8427c6: Pull complete
7c88599c0b25: Pull complete
25b5c6debdaf: Pull complete
43a5816f1617: Pull complete
1a8c919e89bf: Pull complete
9f3cf4bd1a07: Pull complete
80539cea118d: Pull complete
201b3cad54ce: Pull complete
944ba37e1c06: Pull complete
Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
上面的命令是拉取最新的MySQL镜像。然后查看下载的镜像。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest c8562eaf9d81 2 months ago 546MB
从结果可以看到,已经有了 mysql 的 image,然后我们启动运行容器,命令如下。
% docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
19949fb03dd9700bb9e57524317fca477c0407d82ae1ff0cbdd4669b0af6c778
我们来查看容器的状态。
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
19949fb03dd9 mysql "docker-entrypoint.s…" 53 seconds ago Up 52 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-test
此时就可使用 Navicat 等客户端工具来连接 MySQL 了。当然也可以进入 Docker 中进行管理。
% docker exec -it mysql-test /bin/bash
root@19949fb03dd9:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 42726
Server version: 8.0.23 MySQL Community Server - GPL
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
使用 docker exec 命令进入 Docker 后,然后直接使用 mysql 的命令来操作 MySQL。
无论是创建库,还是创建表,包括写一些 SQL 命令看起来一切安好。
小坑
上面看起来还都不错,但是在运行本地的程序时竟然出现了一个报错,报错如下:
bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'test.SYS_CONFIG' doesn't exist
上面的报错是提示表不存在,但是经过确认后该表是存在的,可能是表名大小写的问题?查看一下。
mysql> show variables like '%case%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| lower_case_file_system | OFF |
| lower_case_table_names | 0 |
+------------------------+-------+
2 rows in set (0.00 sec)
配置中 lower_case_table_names 的值为 0,该参数被指定为 0 的时候,那么存储时是按照指定的大小写进行存储的,且在读取时是区分大小写的。该参数如果为 1 时,那么在存储时是使用小写进行存储的,且在读取时是不区分大小的。该值的配置还有 2,这里就不讨论了,而且文档中介绍,只要使用 InnoDB,无论在哪个平台(Linux、MacOS、Windows)下,该参数都要给 1。
那么我们就需要将 lower_case_table_name 的值设置为 1 才可以。
通常情况下,这种参数我们会通过 my.cnf 来进行设置,因此在my.cnf文件中,增加配置项:
lower_case_table_names=1
修改完配置,然后重启 MySQL 的容易,命令如下。
% docker restart 19949fb03dd9
其中 19949fb03dd9 替换为自己的 container id。在命令行重启后没有什么提示,但是 MySQL 不能使用。检查日志,发现启动失败,在日志中存在错误提示:
[ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('1') and data dictionary ('0').
配置文件与数据字典的配置不同,从而导致无法启动。数据字典是在 MySQL 数据库服务器初始化时设置的,而配置则不能与数据字典不一致,这是 MySQL 的一个限制。因此,我们需要重新创建一个 MySQL 的容器,并在启动时给 lower-case-table-names 参数设置为 1 即可。
% docker run -itd --name mysql-new -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql --lower-case-table-names=1
5669d0d7c1776d2dc296a334484855f3c0c0a7d48d917e98d532e3a50b9c66d5
% docker exec -it mysql-new /bin/bash
root@5669d0d7c177:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 86
Server version: 8.0.23 MySQL Community Server - GPL
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show variables like '%case%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| lower_case_file_system | OFF |
| lower_case_table_names | 1 |
+------------------------+-------+
2 rows in set (0.00 sec)
这样 MySQL 的小坑就解决了。
总结
以前使用 MySQL 没有遇到过此类的问题,这也是在 Docker 中使用 MySQL 时遇到的问题。