Docker实现Mysql8主从配置

1 使用docker下载mysql镜像,默认下载最mysql最新版本,目前版本号为8.0.13,如果需要其他版本请登录https://hub.docker.com/进行搜索

[root@localhost ~]#  docker pull mysql

2 下载完毕后分别创建/home/docker/mysql/mysql-3306-data、mysql-3307-data 这五个文件夹,其中mysql-3306-data、mysql-3307-data这两个文件夹用来保存mysql数据,否则docker rm 容器id/容器name 都会删除数据库中的数据

[root@localhost ~]# cd /home

[root@localhost home]# mkdir docker

[root@localhost home]# cd docker

[root@localhost docker]# mkdir mysql

[root@localhost docker]# cd mysql

[root@localhost mysql]# mkdir mysql-3306-data

[root@localhost mysql]# mkdir mysql-3307-data

3 再创建mysql-3306.cnf、mysql-3307.cnf自定义mysql配置文件,用来配置mysql

[root@localhost mysql]# touch mysql-3306.cnf

[root@localhost mysql]# touch mysql-3307.cnf

4 编辑自定义mysql配置文件,复制下列代码
复制分后一定要对比原文!!!

4.1 mysql-3306.cnf文件复制:

[mysqld]

datadir = /var/lib/mysql

server-id = 1

log-bin = mysql-bin

sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

4.2 mysql-3307.cnf文件复制:

[mysqld]

datadir = /var/lib/mysql

server-id = 2

log-bin = mysql-bin

sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

4.3 配置文件说明

4.3.1 本例只是简单配置,详细配置请搜索my.cnf详细配置,sql_mode值含义请看文章第二部分:sql_mode值的含义

4.3.2 server-id是唯一的,主从不能相同,server-id为1表示mysql-3306的数据库为主数据库,server-id为2表示mysql-3307的数据库为从数据库

5 按Esc后,输入wq保存退出

6 启动mysql主从容器

docker run --restart=always --name mysql-3306 -v /home/docker/mysql/mysql-3306.cnf:/etc/my.cnf -v /home/docker/mysql/mysql-3306-data:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
docker run --restart=always --name mysql-3307 -v /home/docker/mysql/mysql-3307.cnf:/etc/my.cnf -v /home/docker/mysql/mysql-3307-data:/var/lib/mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql

6.4 以下为启动命令说明和注意事项,属于延伸阅读,有时间和兴趣可以看一下,不属于配置过程,执行配置请直接跳到步骤 7

6.4.1 命令参数:-v /home/docker/mysql/mysql-3306.cnf:/etc/mysql/mysql-3306.cnf ,将宿主机/home/docker/mysql/目录下的mysql自定义配置文件mysql-3306.cnf挂载到mysql容器的/etc/my.cnf 文件上,相当于我们将mysql-3306.cnf配置文件的内容映射到mysql容器的/etc/my.cnf 文件上,这样mysql容器启动时就不会加载/etc/mysql/下mysql默认的my.cnf配置文件,而去加载/etc/下的my.cnf配置文件,而我们自定义的mysql-3306.cnf配置文件中的内容就会生效

6.4.1.1 为何必须挂载到/etc/my.cnf 文件上,而不是/etc/mysql/my.cnf 文件上?因为mysql默认配置文件位置在/etc/mysql/my.cnf,挂在方式无法改变容器中文件内容,my.conf内容不会改变,my.cnf中没有我们自定义的配置内容,启动mysql容器会报错

6.4.2 命令参数:-v /home/docker/mysql/mysql-3306-data:/var/lib/mysql 让我们回顾一下,刚才在自定义mysql配置文件中还指定了datadir = /var/lib/mysql,datadir表示数据存储目录,现在回到该命令中来,该命令是将mysq容器中,mysql配置文件中指定的数据存储目录/var/lib/mysql下文件的内容共享到宿主机/home/docker/mysql/mysql-3306-data目录下

6.1.2.1 为何必须挂载 /var/lib/mysql 目录?有状态容器都有数据持久化需求,在容器的生命周期内,数据持久化是持续的,包括容器在被停止后,但当容器被删除后,数据也随之被删除了,因此Docker 采用 volume (卷)的形式来向容器提供持久化存储,如果不设置该命令,数据库中的数据会默认保存在mysql容器中的/var/lib/mysql目录下,这样当执行 docker rm 容器id/容器name 命令,会丢失数据库中的数据

7 启动mysql容器以后查看mysql容器状态

[root@localhost mysql]# docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS   
        
f3dd58204c4f        mysql           "docker-entrypoint..."     5 seconds ago      Up 2 seconds

7.1 如果STATUS状态是Up表示成功启动容器,如果STATUS状态是Exited (1) 或者 Restarting (1) 表示未能正常启动,这时候我们需要查看mysql容器日志修改配置文件内容重新运行容器

[root@localhost mysql]# docker logs mysql-3306|less

7.2 查找出问题后停止mysql容器

[root@localhost mysql]# docker stop mysql-3306

7.3 删除mysql容器

[root@localhost mysql]# docker rm mysql-3306

7.3 重新执行步骤 6

8 设置权限、更新密码算法、便于使用Navicat连接,分别进入mysql主从容器中

[root@localhost mysql]# docker exec -it mysql-3306 /bin/bash

[root@localhost mysql]# docker exec -it mysql-3307 /bin/bash

8.1 以下操作在mysql-3306容器、mysql-3307容器中完全相同,故只展示一遍,实操中需要执行两次

8.1.1 输入账号密码

root@zhangqian527halbin:/# mysql -u root -p 

8.1.2 设置权限(为root分配权限,以便可以远程连接)

mysql> grant all PRIVILEGES on *.* to root@'%' WITH GRANT OPTION;

Query OK, 0 rows affected (0.01 sec)

8.1.3 由于Mysql5.6以上的版本修改了Password算法,这里需要更新密码算法,便于使用Navicat连接,如果密码不是‘123456’,请在BY后替换自己的密码

mysql> ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password BY'123456';
Query OK, 0 rows affected (0.01 sec)

8.1.4 刷新MySQL的系统权限相关表

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)

8.1.5 执行完毕后退出mysql

mysql> exit

8.16 退出mysql容器

root@zhangqian527halbin:/# exit

9 使用navicat连接3306,3307

image.png

10 主库mysql-3306上,查询执行sql: SHOW MASTER STATUS ,并复制红框中的值mysql-bin.000004、155

Docker实现Mysql8主从配置_第1张图片
image.png

11 从库mysql-3307上,查询执行sql: STOP SLAVE ,停止slave

Docker实现Mysql8主从配置_第2张图片
image.png

12 从库mysql-3307上,配置主库连接,使用root用户,查询执行sql:

CHANGE MASTER TO MASTER_HOST='192.168.43.234',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=155;
Docker实现Mysql8主从配置_第3张图片
image.png

[注:,MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=155;要和主库mysql-3306上面SHOW MASTER STATUS,后复制红框中的值mysql-bin.000006、2875的时候得到的值一致]

13 从库mysql-3307上,查询执行sql: START SLAVE ,启动slave

Docker实现Mysql8主从配置_第4张图片
image.png

13.1 如果遇到报错:Slave failed to initialize relay log info structure from the repository

Docker实现Mysql8主从配置_第5张图片
image.png

13.2 由于mysql.slave_relay_log_info表中保留了以前的复制信息,导致新从库启动时无法找到对应文件,我们清理掉该表中的记录就可以了
再次提醒,不要手动删该表数据,MySQL已经提供命令:RESET SLAVE
RESET SLAVE做了什么:
1、删除slave_master_info ,slave_relay_log_info两个表中数据;
2、删除所有relay log文件,并重新创建新的relay log文件;
3、不会改变gtid_executed 或者 gtid_purged的值
在MySQL主从结构下,Slave服务器会产生三种日志文件,用来保存主库的二进制日志事件以及relay log已执行到的位置和状态。
1、relay log 文件:**由IO thread线程从主库读取的二进制日志事件组成,该日志被Slave上的SQL thread线程执行,从而实现数据的复制。
2、master info log:该文件保存slave连接master的状态以及配置信息,如用户名,密码,日志执行的位置等。在5.6版本之前,都是使用master.info文件,从5.6开始,通过在my.cnf 中配置 master-info-repository=TABLE这些信息会被写入mysql.slave_master_info 表中,代替原来的master.info文件了
3、relay log info log:该文件保存slave上relay log的执行位置。在5.6版本之前,都是使用relay-log.info文件,从5.6开始,通过在my.cnf中配置 relay-log-info-repository=TABLE,使用mysql.slave_relay_log_info表代替原来的文件,每次当slave上执行start slave时,就会读取该表中的位置信息
查询执行sql: RESET SLAVE

Docker实现Mysql8主从配置_第6张图片
image.png

13.3 再次执行13 从库mysql-3307上,查询执行sql: START SLAVE ,启动slave

Docker实现Mysql8主从配置_第7张图片
image.png

14 从库mysql-3307上,查询执行sql: SHOW SLAVE STATUS ,查看slave状态,Slave_IO_State的值为Waiting for master to send event,则说明配置成功

Docker实现Mysql8主从配置_第8张图片
image.png

15 配置完成,测试主从复制,在主库mysql-3306上创建数据库、表,看看是否mysql-3307也同步
3306上执行,主库mysql-3306上查询执行sql: CREATE DATABASE test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

16 然后navicat上刷新mysql-3307,发现mysql-3307上也创建有test库了,说明主从同步成功,可以接着测试创建表、对表的数据进行增删改进行测试,主库mysql-3306上查询执行sql:

CREATE TABLE `user` (
`id`  int NOT NULL AUTO_INCREMENT ,
`user_name`  varchar(50) NULL ,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
;

17 注意,千万不要直接在mysql-3307从库中删除数据库,否则从库mysql-3307报错,无法主从同步

17.1 在mysql-3307上,查询执行sql: SHOW SLAVE STATUS ,向右拖拽,查看Last_SQL_Error状态,可以看到mysql-3307从库无法同步的错误

Docker实现Mysql8主从配置_第9张图片
image.png

sql_mode值的含义

sql_mode: 含义
ONLY_FULL_GROUP_BY 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么将认为这个SQL是不合法的,因为列不在GROUP BY从句中
STRICT_TRANS_TABLES 在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做任何限制**
NO_ZERO_IN_DATE 在严格模式,不接受月或日部分为0的日期。如果使用IGNORE选项,我们为类似的日期插入'0000-00-00'。在非严格模式,可以接受该日期,但会生成警告。
NO_ZERO_DATE 在严格模式,不要将 '0000-00-00'做为合法日期。你仍然可以用IGNORE选项插入零日期。在非严格模式,可以接受该日期,但会生成警告
ERROR_FOR_DIVISION_BY_ZERO 在严格模式,在INSERT或UPDATE过程中,如果被零除(或MOD(X,0)),则产生错误(否则为警告)。如果未给出该模式,被零除时MySQL返回NULL。如果用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操作结果为NULL。
NO_AUTO_CREATE_USER 防止GRANT自动创建新用户,除非还指定了密码。
NO_ENGINE_SUBSTITUTION 如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常。

mysql5.0以上版本支持三种sql_mode模式:

sql_mode: 含义
ANSI 宽松模式,对插入数据进行校验,如果不符合定义类型或长度,对数据类型调整或截断保存,报warning警告。
TRADITIONAL 严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不能插入,报error错误。用于事物时,会进行事物的回滚。
STRICT_TRANS_TABLES 严格模式,进行数据的严格校验,错误数据不能插入,报error错误。

注意:自定义mysql配置文件中如果设置sql_mode=ONLY_FULL_GROUP_BY,则执行sql时会报错:

Error Code: 1055. Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column '×××' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

所以sql_mode中最好去掉ONLY_FULL_GROUP_BY参数

你可能感兴趣的:(Docker实现Mysql8主从配置)