Java开发 - MySQL主从复制初体验

news/2024/11/27 8:38:52/

前言

前面已经学到了很多知识,大部分也都是偏向于应用方面,在应用实战这条路上,博主一直觉得只有实战才是学习中最快的方式。今天带来主从复制给大家,在刚刚开始动手写的时候,才想到似乎忽略了一些重要的东西,不过还好,既然想到了,就会在本文中体现出来,争取让大家学完之后明白主从复制的原理和怎么去做主从复制。

什么是主从复制

MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现 从库 的数据和 主库 的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。

​二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用,MySQL的主从复制, 就是通过该binlog实现的。默认MySQL是未开启该日志的。

主从复制分为三步完成:

  • MySQL master 将数据变更的SQL语句写入二进制日志( binary log)
  • slave将master的binary log拷贝到它的中继日志(relay log),说是拷贝,其实是读取过来,也可以理解成拷贝,内容拷贝
  • slave读取中继日志中的事件,将数据变更反映它自己的数据库中

Docker模拟多服务器准备

博主没有办法在真正的两台云端服务器上给大家做演示,所以就在本地给大家模拟一下做法,有虚拟机的使用虚拟机复制出来一个使用,没有虚拟机的可以使用Docker来模拟。

使用Docker模拟时,需要创建两个mysql的容器:

Master(主):

docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql

Slave(从):

docker run -p 3309:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 -d mysql

博主没有指定版本,因为博主Image内已经存在一个最新的版本,如果使用的版本略低,可手动指定: 

docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:x.x.x

这里需要说明一下端口,由于非生产环境,本地模拟时,端口需要映射,不能全都用3306,所以slave中映射了3309,否则容器启动会因为端口冲突报错。

此时在Docker内,已经有两个运行中的mysql了:

docker ps可以查看运行中的容器:

配置数据库主从

配置Master

docker exec -it 8e46c78ba828 /bin/bash

输入上面的命令,进入master容器内部,8e46c78ba828是容器id,也可以使用容器名mysql进入:

docker exec -it mysql /bin/bash

输入:

cd /etc/mysql

进入mysql的配置文件目录下,对my.cnf进行编辑:

vi my.cnf

正常是会报错的,会提示:

bash: vi: command not found

需要我们在docker内安装vim,这个我们在前面的博客中有提到,为了方便,此处再写一下解决步骤:

输入

apt-get install vim

提示:

Reading package lists... Done

Building dependency tree       

Reading state information... Done

E: Unable to locate package vim

输入

apt-get update

 

然后输入

apt-get install vim

等待vim安装完成即可。

注意里面会有一个提示,输入Y。安装过程可能会有点慢,稍安勿躁。

安装完成,此时再输入以下命令:

vi my.cnf

在最下面增加配置:

log-bin=mysql-bin   #[必须]启用二进制日志
server-id=100       #[必须]服务器唯一ID(唯一即可)

然后退出保存即可。下面要重启mysql服务,让配置生效:

你可以选择使用命令行

service mysql restart

甚至你还需要重启mysql容器:

docker start mysql

但博主这里偷懒,直接在docker内部重启mysql容器,哈哈!!!

特别注意:你目前所在的文件夹是:root@8e46c78ba828:/etc/mysql

你需要通过两次cd ..回到顶端目录,然后使用:

mysql -uroot -pxxxx

u后面跟账号,p后面跟密码,登录到mysql内:

以上启动sql的命令运行在root@8e46c78ba828:/etc/mysql目录下是不行的,需要你退出docker容器运行才可以,这个是常识哈,我当大家都知道的。

下一步在Master数据库创建数据同步用户,授予slave的访问用户,比如slave,授权 REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据,分两步完成:

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

到这里,主库的配置就算是完成了,你可以输入:

show master status;

 来查看主库的状态:此时主库什么都不要动,这里的File和Position我们后面有用。

配置Salva

接下来我们来配置从库,整体步骤和主库差不多,但是为了让大家不出错,这里还是一步步带着大家操作。

首先新开一个终端窗口:

docker exec -it e2476006aeb4 /bin/bash

输入上面的命令,进入slave容器内部,e2476006aeb4是容器id,也可以使用容器名mysql-slave进入:

docker exec -it mysql-slave /bin/bash

输入:

cd /etc/mysql

进入mysql的配置文件目录下,对my.cnf进行编辑:

vi my.cnf

不出意外的又报错了,还是和主库一样,这是因为两个容器互不相关,所以还需要在此容器安装vim,步骤一样,大家照着上面来。

安装完成,此时再输入以下命令:

vi my.cnf

在最下面增加配置:

log-bin=mysql-bin   #[必须]启用二进制日志
server-id=101       #[必须]服务器唯一ID(唯一即可)

然后退出保存即可。下面要重启mysql服务和容器,让配置生效。这里注意,id变了,主库是100,此处是101。

关联主从数据库

进入从数据库中,登陆了从数据库,执行以下命令,设置主库地址及同步位置

change master to master_host='172.17.0.2',master_user='slave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=721;

来解释下这里的数据来源。

ip通过以下命令获得:

docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器id/容器名

master_log_file='mysql-bin.000001',master_log_pos=721;还记得我们通过show master status获得的表格吗?

看看数据对不对的上。

然后执行:

start slave;

为了验证主从关联是否完成,在从库Slave中输入以下命令:

show slave status \G;

\G是因为让显示是一行一行的,否则表格太长,无法直观的看到想要的信息。 

查看SlaveIORunning 和 SlaveSQLRunning 都是Yes,说明主从复制已经开启。

 此时,SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,查看错误:

error connecting to master 'slave@172.17.0.2:3306' - retry-time: 60 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.

提示我们授权有问题,详情可查看此篇博客:Authentication plugin 'caching_sha2_password' reported error:Authentication..我们采用这篇博客说的第三种办法去解决这个问题,避免使用caching_sha2_password插件,所以我们需要重新创建一个用户:

CREATE USER 'repl'@'%' IDENTIFIED WITH 'mysql_native_password' BY '123456';

前面做的时候没有做远程授权,也会报错,所以这里加上了授权远程访问的权限: 

GRANT ALL PRIVILEGES ON *.* TO 'repl'@'%'  WITH GRANT OPTION;

我们查看下数据库中用户的列表:

一定要有远程访问的权限才可以,Grant_priv就是,虽然slave用户也授权了远程权限,但是使用了caching_sha2_password,也不可用,所以才新建了repl用户。接着,我们要查看主库的状态,重新获取关键信息:

show master status;

查看主库状态:

发现原来的 721变了,File的文件后缀名也变为02了。这里要注意,一定要用新的,到这里,主库千万不要再去动了,否则会出别的问题。

下面在从库重新关联主从,在这之前,需要先停止slave:

stop slave;
reset slave;

然后执行此命令关联:

change master to master_host='172.17.0.2',master_user='repl',master_password='123456',master_log_file='mysql-bin.000002',master_log_pos=2819;

注意参数改为2819,接着启动slave:

start slave;

 查看关联状态:

show slave status \G;

看到两个YES,就说明主从已经配置好了。  

关于mysql的授权相关命令,推荐一篇博客给大家:MySql 授权命令grant

测试主从

我们在使用Docker内部IP访问数据库的时候发现无法连接,这是因为这个IP是docker内部id,博主查了很多资料,都没有很好的解决这个问题,但是,也看到了一些说法:

如何访问docker容器ip-Docker-PHP中文网

根据这篇博客,最终得到的结论就是,虽然无法直接访问docker内部ip,但是我们已经通过端口映射到了localhost的端口上,所以,可以把docker内部ip地址换成主机地址,也可以直接用localhost,port使用映射的端口就可以。

还有另一篇博客:

 解决docker宿主机不能访问容器的问题_docker宿主机访问不到容器 

这篇博客提出在创建容器的时候,容器与宿主机共享同一个网卡,不过博主没有重新创建容器,有兴趣的小伙伴自行尝试。 

此时我们通过localhost链接主从数据库,由于主数据库源本来就存在其他的数据库,从库是新的,连接上之后,完全没有问题,俩数据库绝对是完全不一样的,我们使用localhost的做法也是正确的,这位我们测试主从提供了良好的环境。

下面开始测试,在主数据库创建数据库,并创建新表:

create database if not exists master_slave character set utf8;
use master_slave;
CREATE TABLE user (id bigint(20) primary key auto_increment,username varchar(32) not null,password  varchar(32) not null,age int(3) not null ,phone varchar(32) not null
)

 此时用户表已经创建完毕,我们去从库看一下这个表有没有被创建出来:

从库里面已经出现了数据库和用户表,非常棒,主从完美啊,我们在主库用户表添加点数据看看: 

insert into user value(null ,'codingfire','123456',20,'13812345678');

查看主库表:

用户信息已经插入,切换到从库查看:

从库也有了,主从复制测试成功。删除修改大家可以自行测试。 

注意:细心点,你会发现页面左上角的数据库连接对象是不一样的,所以这里连接docker使用localhost是完全没有问题的。另外,如果docker异常关机等,导致同步的游标出现错乱,需要重新配置日志游标:

stop slave;
change master to master_log_file='mysql-bin.00000x', master_log_pos=xxxx;
start slave;

结语

总的来说,mysql的主从还是没那么复杂的,没有代码操作,全都是配置,在真实的服务器上,配置也基本都是这样,这里学会了,真实的服务器也不在话下。虽然主从复制写完了,但是关于主从的只是只是还没有结束,因为还没在项目中引入主从的使用,下一篇,我们将学习主从在项目中的使用——读写分离。觉得不错,就给博主个赞吧。


http://www.ppmy.cn/news/43040.html

相关文章

Ubuntu搭建web站点并发布公网访问【内网穿透】

文章目录前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子域名前言 网:我们通常说的是互联网;站…

蓝牙设备如何自定义UUID

如何自定义UUID 所有 BLE 自定义服务和特性必须使用 128 位 UUID 来识别,并且要确保基本 UUID 与 BLE 定义的基本 UUID(00000000-0000-1000-8000-00805F9B34FB)不一样。基本 UUID 是一个 128 位的数值,根据该值可定义标准UUID&am…

ACM8629 立体声50W/100W单声道I2S数字输入D类音频功放IC

概述 ACM8629 一款高度集成、高效率的双通道数字输入功放。供电电压范围在4.5V-26.4V,数字接口电源支持3.3V 。在4 欧负载,BTL模式下输出功率可以到250W1%THDN,在2欧负载,PBTL模式下单通道可以输出1100W 1%THDN. ACM8629采用新型PWM脉宽调制架…

C++标准库--IO库(Primer C++ 第五版 · 阅读笔记)

C标准库--IO库(Primer C 第五版 阅读笔记)第8章 IO库8.1、IO类8.2、文件输入输出8.3、string流总结:第8章 IO库 8.1、IO类 为了支持这些不同种类的IO处理操作,在istream和ostream之外,标准库还定义了其他一些IO类型。 如下图分…

学习系统编程No.20【进程间通信之命名管道】

引言: 北京时间:2023/4/15/10:34,今天起床时间9:25,睡了快8小时,昨天刷视屏刷了一个小时,本来12点的时候发完博客洗把脸就要睡了,可惜,看到了一个标题,说实话&#xff0…

基于 Git 的开发工作流——主干开发特性总结

在参与开发的过程,得益与平台提供便捷的开发流程,简化很多开发过程操作分支的步骤;也就很好奇,为什么研发平台怎么设计,考虑的点是为什么,便有了这次对主干研发的学习与记录。当我们是构建软件项目的唯一开…

Qt Quick - 弹出控件综述

Qt Quick - 弹出控件综述一、概述一、抽屉控件二、菜单控件三、弹出控件四、工具提示控件一、概述 控件功能Dialog带有标准按钮和标题的弹出式对话框,用于与用户进行短期交互Drawer可以用滑动手势打开和关闭的侧面板Menu弹出式菜单,可以用作上下文菜单或…

Sharding-JDBC之水平分表

目录一、简介1.1、垂直分表1.2、水平分表二、maven依赖三、数据库3.1、创建数据库3.2、创建表四、配置(二选一)4.1、properties配置4.2、yml配置五、实现5.1、实体5.2、持久层5.3、服务层5.4、测试类5.4.1、保存数据5.4.2、查询数据一、简介 1.1、垂直分…