Docker实现Mysql8主从配置

1.关闭防火墙,否则Mysql从机无法找到主机,查看防火墙状态,绿色running表示防火墙开启

[root@localhost ~]#  systemctl status firewalld.service

执行关闭命令

[root@localhost ~]#  systemctl stop firewalld.service

再次执行查看防火墙命令

[root@localhost ~]#  systemctl status firewalld.service

执行开机禁用防火墙自启命令

[root@localhost ~]#  systemctl disable firewalld.service

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

[root@localhost ~]#  docker pull mysql

3 下载完毕后分别创建/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

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

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

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

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

5.1 mysql-3306.cnf文件复制:

[mysqld]

datadir = /var/lib/mysql

server-id = 1

log-bin = mysql-bin

sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

5.2 mysql-3307.cnf文件复制:

[mysqld]

datadir = /var/lib/mysql

server-id = 2

log-bin = mysql-bin

sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

5.3 配置文件说明

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

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

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

7 启动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

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

7.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配置文件中的内容就会生效

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

7.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目录下

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

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

[root@localhost mysql]# docker ps -a

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

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

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

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

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

8.3 删除mysql容器

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

8.3 重新执行步骤 7

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

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

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

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

9.1.1 输入账号密码,密码为第6部执行的命令-e MYSQL_ROOT_PASSWORD=123456,该命令指定mysql容器root用户的密码

root@1862c89783a0:/# mysql -u root -p 

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

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

Query OK, 0 rows affected (0.01 sec)

9.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)

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

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

9.1.5 执行完毕后退出mysql

mysql> exit

9.16 退出mysql容器

root@1862c89783a0:/# exit

10 使用navicat连接3306,3307

image.png

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

image.png

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

image.png

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

CHANGE MASTER TO MASTER_HOST='192.168.43.2',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=155;
image.png

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

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

image.png

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

image.png

14.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

image.png

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

image.png

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

image.png

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

17 然后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
;

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

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

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参数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容