最近需要用到mysql,直接用docker-compose安装快速简单,但是安装过程遇到很多问题,这里分享遇到的一些坑。
准备工作
创建宿主机目录
mkdir /docker/mysql/conf
mkdir /docker/mysql/data
mkdir /docker/mysql/log
创建docker-compose文件
version: '3'
services:
mysql-master: # 服务名称
image: mysql:8.0.18 # 或其它mysql版本
container_name: mysql8-master # 容器名称
environment:
- MYSQL_ROOT_PASSWORD=123456 # root用户密码
# - TZ=Asia/Shanghai # 设置容器时区 我这里通过下面挂载方式同步的宿主机时区和时间了,这里忽略
volumes:
- /docker/mysql/log:/var/log/mysql # 映射日志目录,宿主机:容器
- /docker/mysql/data:/var/lib/mysql # 映射数据目录,宿主机:容器
- /docker/mysql/conf.d:/etc/mysql/conf.d # 映射配置目录,宿主机:容器
- /etc/localtime:/etc/localtime:ro # 让容器的时钟与宿主机时钟同步,避免时间的问题,ro是read only的意思,就是只读。
ports:
- 3306:3306 # 指定宿主机端口与容器端口映射关系,宿主机:容器
restart: always # 容器随docker启动自启
#command: --lower_case_table_names=1
mysql-slave: # 从服务名称
image: mysql:8.0.18 # 或其它mysql版本
container_name: mysql8-slave # 容器名称
environment:
- MYSQL_ROOT_PASSWORD=y2@S^!H9XQaz # root用户密码
# - TZ=Asia/Shanghai # 设置容器时区 我这里通过下面挂载方式同步的宿主机时区和时间了,这里忽略
volumes:
- /docker/mysql-slave/log:/var/log/mysql # 映射日志目录,宿主机:容器
- /docker/mysql-slave/data:/var/lib/mysql # 映射数据目录,宿主机:容器
- /docker/mysql-slave/conf.d:/etc/mysql/conf.d # 映射配置目录,宿主机:容器
- /etc/localtime:/etc/localtime:ro # 让容器的时钟与宿主机时钟同步,避免时间的问题,ro是read only的意思,就是只读。
ports:
- 3307:3306 # 指定宿主机端口与容器端口映射关系,宿主机:容器
restart: always # 容器随docker启动自启
#command: --lower_case_table_names=1
创建master的my.cnf文件
###### [client]配置模块 ######
[client]
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock
###### [mysql]配置模块 ######
[mysql]
# 设置MySQL客户端默认字符集
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock
###### [mysqld]配置模块 ######
[mysqld]
user=mysql
# 设置sql模式 sql_mode模式引起的分组查询出现*this is incompatible with sql_mode=only_full_group_by,这里最好剔除ONLY_FULL_GROUP_BY
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# MySQL8 的密码认证插件 如果不设置低版本navicat无法连接
default_authentication_plugin=mysql_native_password
# 禁用符号链接以防止各种安全风险
#skip-symbolic-links
# 允许最大连接数
max_connections=1000
max_allowed_packet=500M
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 表名存储在磁盘是小写的,但是比较的时候是不区分大小写
lower_case_table_names=1
max_allowed_packet=16M
# 设置时区
#default-time_zone='+8:00'
log_timestamps=SYSTEM
# 设置错误日志路径
log-error=/var/log/mysql/error.log
#binlog配置
server_id=1
# [必须]启用二进制日志
log-bin=mysql-bin
# 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
# 确保binlog日志写入后与硬盘同步
sync_binlog = 1
# 跳过所有的错误,继续执行复制操作
slave-skip-errors = all
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
# 设置慢查询日志路径
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
### SSL settings ###
ssl-ca = /var/lib/mysql/ca.pem
ssl-cert = /var/lib/mysql/server-cert.pem
ssl-key = /var/lib/mysql/server-key.pem
# 结束这个反查的过程,禁止任何解析。
skip-name-resolve=1
创建slave的my.cnf文件
###### [client]配置模块 ######
[client]
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock
###### [mysql]配置模块 ######
[mysql]
# 设置MySQL客户端默认字符集
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock
###### [mysqld]配置模块 ######
[mysqld]
user=mysql
# 设置sql模式 sql_mode模式引起的分组查询出现*this is incompatible with sql_mode=only_full_group_by,这里最好剔除ONLY_FULL_GROUP_BY
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# 不同步test数据库 可以写多个例如 binlog-ignore-db = mysql,information_schema
replicate-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
# 跳过所有的错误,继续执行复制操作
slave-skip-errors = all
# MySQL8 的密码认证插件 如果不设置低版本navicat无法连接
default_authentication_plugin=mysql_native_password
# 禁用符号链接以防止各种安全风险
#skip-symbolic-links
# 允许最大连接数
max_connections=1000
max_allowed_packet=500M
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 表名存储在磁盘是小写的,但是比较的时候是不区分大小写
lower_case_table_names=1
max_allowed_packet=16M
# 设置时区
#default-time_zone='+8:00'
log_timestamps=SYSTEM
# 设置错误日志路径
log-error=/var/log/mysql/error.log
#binlog配置
server_id=2
# [必须]启用二进制日志
log-bin=mysql-bin
# 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
# 确保binlog日志写入后与硬盘同步
sync_binlog = 1
# 跳过所有的错误,继续执行复制操作
slave-skip-errors = all
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
# 设置慢查询日志路径
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
### SSL settings ###
ssl-ca = /var/lib/mysql/ca.pem
ssl-cert = /var/lib/mysql/server-cert.pem
ssl-key = /var/lib/mysql/server-key.pem
# 结束这个反查的过程,禁止任何解析。
skip-name-resolve=1
启动容器
docker-compose -f docker-compose.yml up -d
主库创建复制用户
这里需要指定密码类型,MySQL8默认类型从库无法连接
CREATE USER ''@'%' IDENTIFIED WITH 'mysql_native_password' BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';
查询主库状态
可以获取到从库连接主库的参数,master_log_file和master_log_pos
show master status;
从库连接主库
change master to master_host='192.168.50.200', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000004', master_log_pos=155, master_connect_retry=30;
- master_host :Master的地址。 由于这里使用docker容器部署,采用桥接模式,IP需要填写宿主机IP
- master_port:Master的端口号
- master_user:用于数据同步的用户,这里填我们新创建的用户主从同步的用户
- master_password:用于同步的用户的密码
- master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上面主库中 File 字段的值
- master_log_pos:从哪个 Position 开始读,即上面主库 Position 字段的值
- master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
从库开启同步
start slave;
从库关闭同步
stop slave;
查询从库同步状态
show slave status;
下面这两个Yes则表示状态正确
注意,查询主库状态里的文件位置是开始的位置,如果之前就有没有同步的需要手动同步,并不会自动同步,是开启同步之后的才会进行同步。
遇到的坑
my.cnf无法生效
World-writable config file ‘/etc/my.cnf’ is ignored
可以检查你的映射的日志目录有没有日志文件生成,没有则没有生效。这是自己创建的导致文件权限不是640,所以无法生效,被忽略了。
chmod 644 my.cnf
忽略表大小写
在my.cnf里设置了忽略表大小写,也是无法生效,查询文档发现当你创建容器的时候设置后就不能更改了,所以只能初始化设置,有两种方法,第一种在docker-compose文件加上command: --lower_case_table_names=1,第二种在my.cnf配置lower_case_table_names=1
日志时间不同步的问题
需要在my.cnf设置log_timestamps=SYSTEM
提示Please use caching_sha2_password instead'
连接
Mysql
的客户端不支持sha256_password
或者caching_sha2_password
的加密方式。my.cnf添加default_authentication_plugin=mysql_native_password
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
提示Name or service not known
my.cnf添加skip-name-resolve
Failed to set up SSL
第一次启动会产生SSL相关的证书,所以只需要在my.cnf配置下面证书的路径即可。
### SSL settings ###
ssl-ca = /var/lib/mysql/ca.pem
ssl-cert = /var/lib/mysql/server-cert.pem
ssl-key = /var/lib/mysql/server-key.pem
Disabling symbolic links using --skip-symbolic-links
my.cnf配置skip-symbolic-links