MySQL主从的应用

说明:本文介绍MySQL主从在实际中的应用。主从搭建和问题参考下面两篇文章:

  • MySQL主从结构搭建

  • 搭建MySQL主从结构时的问题

数据迁移

当我们搭建完MySQL主从,第一步当然是把历史数据导入到主从结构中。有以下两种方式:

  • 开启主从同步,将数据导入主节点,让从节点同步;

  • 将数据分别导入主从节点,让主从节点数据一致后,建立连接,开启同步;

不论哪种方式,都需要导出/导入数据。为了节省时间,可以采用mysql命令的方式导出/导入,而不是用数据库连接工具来操作。以xxl-job数据库为例:

数据导出为sql文件

mysqldump -u username -p xxl_job > xxl-job.sql

在这里插入图片描述

在这里插入图片描述

将xxl-job.sql文件上传到MySQL主从的服务器上,导入数据库,这里我导入到test数据库中

mysql -u username -p test < xxl-job.sql

在这里插入图片描述

使用navicat查看,主库里test数据库里面有xxl-job相关的表了,同样的从库也同步过去了。

在这里插入图片描述

应用

一般来说,MySQL主从可以有以下两个应用。

(1)数据备份

就是啥也不做,从库仅做数据备份,另外当主库宕机时,可以修改配置文件,改为从库。但这又会有一个问题,主从库的数据一致性怎么保证。会不会出现一种情况,主库写入的数据,还没来得及同步到从库,然后宕机了。这段时间内的数据是从库中没有的。切换到从库,从库跑了一段时间后又有数据写入。结果就是,主从库之间各自有对方没有的数据,事后怎么同步数据又是问题。

总之,MySQL主从用来做数据备份是OK的,但如果用来做灾备,需要考虑以下问题:

  • 切换从库后,数据一致性怎么保证(看主库日志,看是怎么时候宕机的,这个时间段有没有会话连接,对数据库操作量大不大)

  • 缺失的数据对系统的影响大不大(经验之谈,可能主库宕机,但binlog都推送给从库了,主从库数据一致,完全没影响)

  • 事后主从数据库之间的数据同步怎么搞(能否将各自的数据导出来,各自导入执行一遍或者导出来做比对,针对缺失的数据做导入)

(2)读写分离

读写分离,顾名思义,就是将对数据库的操作分开,读操作分给从库,主库压力会小很多。在博主前面介绍的主从搭建中,有分别对主从配置文件添加下面这行配置:

(主数据库)

# 是否只读,1 代表只读,0代表读写,主数据库需要读写,设置0
read-only=0

(从数据库)

# 是否只读,1 代表只读,0代表读写,从数据库仅读,设置1
read-only=1

但在我实际操作来看,似乎没有生效。从数据库该添加数据还是能添加数据,真正做到读写分离,需要从MySQL账户入手,设置从库的MySQL账户仅有查询操作,然后项目里配置的就是这个账户才行。相关SQL如下:

MySQL权限相关命令

# 创建admin用户
create user 'admin'@'%' identified by 'MySQL@3306';# 赋予该账户select权限
GRANT SELECT ON *.* TO 'admin'@'%';# 刷新
flush privileges;

创建一个仅有select权限的用户,用户名为admin;

在这里插入图片描述

其他命令

# 移除用户的所有权限
REVOKE ALL PRIVILEGES ON *.* FROM 'admin'@'%';
# 根据用户名查询主机设置
select user,host from mysql.user where user = 'admin';

写入测试,提示错误

在这里插入图片描述

读写分离也需要考虑数据一致性问题,为此我们可以考虑如下方案:

  • 当读取返回结果为空时,再读一遍主库;

  • 写操作紧跟着的读操作,访问主库;

  • 核心业务读写主库,非核心业务读从库;

dynamic-datasource组件

该组件提供了多数据源场景的一些功能,包括切换数据源、多数据源事务、多从库的负载均衡策略等,以下介绍一下这个组件的基础功能;

(0)准备工作

首先创建一个Spring Boot项目,文件如下:

(pom.xml文件)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/></parent><groupId>com.hezy</groupId><artifactId>multiple_databases_demo</artifactId><version>1.0-SNAPSHOT</version><name>Archetype - multiple_databases_demo</name><url>http://maven.apache.org</url><dependencies><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--dynamic-datasource--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.1</version></dependency><!--druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><!--msyql驱动--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency></dependencies>
</project>

(创建两个接口,一个读,一个写)

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public User getUser(@PathVariable String id) {return userService.getUser(id);}@PostMapping("/add")public void addUser(@RequestBody User user) {userService.addUser(user);}
}

(1)切换数据库

使用dynamic-datasource组件切换数据库非常简单,首先配置文件里,配置多个数据源,如我搭建的是主从MySQL,则配置如下:

server:port: 8080# 1.数据源的配置
spring:datasource:dynamic:datasource:master:url: jdbc:mysql://主节点IP:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8username: adminpassword: MySQL@3306driver-class-name: com.mysql.cj.jdbc.Driverslave:url: jdbc:mysql://从节点IP:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8username: adminpassword: MySQL@3306driver-class-name: com.mysql.cj.jdbc.Driver# 2.mybatis配置
mybatis:configuration:# 显示SQL日志配置log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 驼峰命名配置map-underscore-to-camel-case: true# 设置mapper.xml文件所在的路径mapper-locations: classpath:mapper/*.xml

使用时,在对应的方法上加上@DS(数据源名称)即可,如下,读操作给从库(slave),写操作给主库(master)

import com.baomidou.dynamic.datasource.annotation.DS;
import com.hezy.pojo.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface UserMapper {@DS("slave")@Select("select * from i_user where id = #{id}")User getUser(String id);@DS("master")@Insert("insert into i_user(id, username, password) values(#{id}, #{username}, #{password})")void addUser(User user);
}

(读操作,走从库)

在这里插入图片描述

(写操作,走主库)

在这里插入图片描述

在这里插入图片描述

更换一下,将写操作分给主库,

import com.baomidou.dynamic.datasource.annotation.DS;
import com.hezy.pojo.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface UserMapper {@DS("master")@Select("select * from i_user where id = #{id}")User getUser(String id);@DS("slave")@Insert("insert into i_user(id, username, password) values(#{id}, #{username}, #{password})")void addUser(User user);
}

重启测试,读操作,没问题

在这里插入图片描述

写操作,报错

在这里插入图片描述

在这里插入图片描述

多数据源切换实现原理是AOP,官方推荐@DS注解加载Service实现类对应的方法上。

(2)数据库配置加密

使用该组件,可以实现对数据库配置的加密,让配置文件中数据库配置显示的是密文。实现如下:

    public static void main(String[] args) throws Exception {// 明文配置String password = "MySQL@3306";// 加密显示String encodePassword = CryptoUtils.encrypt(password);System.out.println(encodePassword);}

将下面这段密文复制下来;

在这里插入图片描述

在配置文件中,如下:

在这里插入图片描述

实现原理是,私钥加密,公钥解密。用以上方法实际上用的是组件自带的私公钥。

在这里插入图片描述

推荐使用下面的方法,随机生成私公钥;

    public static void main(String[] args) throws Exception {// 生成私公钥String[] arr = CryptoUtils.genKeyPair(512);System.out.println("privateKey:  " + arr[0]);System.out.println("publicKey:  " + arr[1]);// 使用私钥加密数据库相关配置System.out.println("username:  " + CryptoUtils.encrypt(arr[0], "admin"));System.out.println("password:  " + CryptoUtils.encrypt(arr[0], "MySQL@3306"));}

在这里插入图片描述

把上面两个配置复制到配置文件中,同时附带上public-key,如下:

spring:datasource:dynamic:datasource:master:url: jdbc:mysql://主库IP:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8username: ENC(oM2ceVnn3KOTEv9Ci4yI4QKwfaSzHZpb26SWQuxlgtcMtYpbr5HYK30TT+jtI+IOsZJHqSaWhhPPlfM40rnYrw==)password: ENC(TvstWlvbEKqPzJrek8fx3+Si6c6OeoiZVE7Njbf+fYwjqb/Tr3v0YevMfdG8FAB32U3xda5J7AdRhAcWA0A1rg==)driver-class-name: com.mysql.cj.jdbc.Driverslave:url: jdbc:mysql://从库IP:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8username: ENC(oM2ceVnn3KOTEv9Ci4yI4QKwfaSzHZpb26SWQuxlgtcMtYpbr5HYK30TT+jtI+IOsZJHqSaWhhPPlfM40rnYrw==)password: ENC(TvstWlvbEKqPzJrek8fx3+Si6c6OeoiZVE7Njbf+fYwjqb/Tr3v0YevMfdG8FAB32U3xda5J7AdRhAcWA0A1rg==)driver-class-name: com.mysql.cj.jdbc.Driverpublic-key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL2RM3JnCjtTogh3LrwN/meyWaWpSGCn7CaYRo6spLaeAhcguhi3XQrfLa7W4LQrJTENm+yA52YJfk+mWtjyl0ECAwEAAQ==

如果你主从库是分开生成的,则在每个数据源里写各自的公钥配置,如果是一样的,如上,主从库用户名、密码一样,就在外层全局设置即可。

另外,提醒一点,用上面的方法每次都会生成新的私公钥,所以需要加密的数据库配置需要是同一次操作生成的,不能跑一遍把username、password加密了,后面感觉url也要加密,就单独把url加密,然后复制到配置里,这样启动时会报解密错误的。

(3)更多

dynamic-datasource组件更丰富的功能,参考官方文档:https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611

总结

本文介绍了MySQL主从的应用,及应用时需要考虑的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python如何安装本地的.whl文件

在Python中&#xff0c;.whl文件&#xff08;也被称为wheel文件&#xff09;是一种二进制包格式&#xff0c;它允许用户在没有源代码的情况下安装Python库。这对于那些没有编译环境或者希望快速安装的用户来说非常有用。在本文中&#xff0c;我们将探讨如何在本地安装.whl文件。…

Linux之 USB驱动框架-usb_submit_urb和usb_fill_*_urb分析(6)

一、usb_fill_*_urb 函数调用流程 // 控制 static inline void usb_fill_control_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, unsigned char *setup_packet, void *t…

CST Studio初级教程 一

本教程将详细介绍CST Studio Project创建。 新建Project 1. 点击New and Recent&#xff0c;然后点击New Template。 然后依据我们的仿真属类&#xff0c;在下图中做选择需要的模板。 如果做高频连接器信号完整性&#xff08;SI&#xff09;仿真&#xff0c;我们就选Microwaves…

数据结构之二叉搜索树底层实现洞若观火!

目录 题外话 正题 二叉搜索树 底层实现 二叉搜索树查找操作 查找操作思路 查找代码实现详解 二叉搜索树插入操作 插入操作思路 插入代码详解 二叉搜索树删除操作 删除操作思路 删除代码详解 小结 题外话 我的一切都是党给的,都是人民给的,都是家人们给的!! 十分感…

Java分布式ID

1 什么是分布式ID 分布式ID是指在分布式系统中生成的唯一标识符&#xff0c;用于标识不同实体或数据的唯一性。在分布式系统中&#xff0c;多台机器并行处理任务&#xff0c;为了确保生成的ID在整个系统中的唯一性&#xff0c;需要采用特殊的算法来生成分布式ID。 在传统的单机…

Docker的数据管理、网络通信和dockerfile

目录 一、Docker的数据管理 1. 数据卷 1.1 数据卷定义 1.2 数据卷配置 2. 数据卷容器 2.1 创建数据卷容器 2.2 使用--volume-from来挂载test1 二、端口映射 三、容器互联 1. 创建容器互联 ​编辑2. 进入test2测试&#xff08;ping 容器名/别名&#xff09; 四、Dock…

Python的pytest框架(5)--测试标记(Markers)

该篇将循序渐进地详细拆解 pytest.mark 装饰器&#xff1a; 目录 一、概念 二、标记的基本结构与使用 三、标记在测试中的层次应用 四、标记的筛选与运行 五、标记与测试行为控制 六、标记与测试参数化 七、标记的注册与自定义 1、通过pytest.ini配置文件&#xff1a;…

SpringBoot钩子函数

在Java Spring Boot中&#xff0c;并没有直接称为“钩子函数”的概念&#xff0c;但你可以通过实现特定的接口、注解、事件监听或使用AOP&#xff08;面向切面编程&#xff09;来实现类似的功能。这些功能允许你在应用的特定点插入自定义逻辑&#xff0c;类似于钩子函数的作用。…

c++11详解

目录 1.列表初始化 2.声明 3.右值引用和移动语句 4. c11新的类功能 5. 可变参数模板 6.lambda表达式 7.包装器 8. 后言 1. 列表初始化 1.1 {}的初始化 (1) c98标准规定可以使用{}对数组以及结构体进行统一的列表初始化. struct Point {int _x;int _y; };int main() {in…

Python数据权限的管理通常涉及到几个关键组件:身份验证,、授权和访问控制。这通常是通过使用数据库、ORM(对象关系映射)框架、API框架和中间件

在Python中&#xff0c;数据权限的管理通常涉及到几个关键组件&#xff1a;身份验证&#xff0c;、授权和访问控制。这通常是通过使用数据库、ORM&#xff08;对象关系映射&#xff09;框架、API框架和中间件等技术来实现的。以下是一些建议的步骤和工具&#xff0c;用于在Pyth…

C语言面经

25.类型相同的两个指针之间不能进行的运算 指针主要用于存储变量的内存地址。对于同类型的指针变量之间&#xff0c;有一些规则&#xff1a; a. 小于运算&#xff08;<&#xff09;&#xff1a;指针间的小于比较是基于它们指向的内存地址。地址较小的指针在小于比较中被认为…

【Unity】shader中参数传递

1、前言 unity shader这个对于我来说是真的有点难&#xff0c;今天这篇文章主要还是总结下最近学习到的一些东西&#xff0c;避免过段时间忘记了&#xff0c;可能有不对&#xff0c;欢迎留言纠正。 2、参数传递的两种方式 2.1 语义传递 语义传递这个相对来说是简单的 shad…

Csharp_pta2_2

7-7 C# 1.12 区间找数 编写控制台应用程序&#xff0c;根据用户输入的a、b、c、d值&#xff08;均为正整数且a不大于b&#xff09;&#xff0c;输出在[a, b]区间中能被c整除&#xff0c;但是不能被d整除的数。 输入格式: 用户在一行中输入四个正整数&#xff0c;分别对应a、…

数组模拟几种基本的数据结构

文章目录 数组模拟单链表数组模拟双链表数组实现栈数组模拟队列总结 数组模拟单链表 首先类比结构体存储单链表&#xff0c;我们需要一个存放下一个节点下标的数组&#xff0c;还需要一个存储当前节点的值的数组&#xff0c;其次就是一个int类型的索引&#xff0c;这个索引指向…

Python 实现视频去抖动技术

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 视频去抖动是视频处理中的一项重要技术&#xff0c;它可以有效地减少视频中由于相机震动或手…

springSecurity简单直接说明

引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombo…

MyBatis处理SQL中的特殊字符

方式一&#xff1a;转义字符 如下案例&#xff1a; < 表示小于的转义字符 <!-- 在Mapper XML文件中定义SQL语句 --> <select id"selectById" resultMap"BaseResultMap">select *from userwhere id < #{id}; </select>方式二&am…

设计模式:依赖倒转原则(Dependency Inversion Principle,DIP)介绍

依赖倒转原则&#xff08;Dependency Inversion Principle&#xff0c;DIP&#xff09;是面向对象设计原则之一&#xff0c;它强调高层模块不应该依赖于底层模块&#xff0c;二者都应该依赖于抽象。同时&#xff0c;抽象不应该依赖于具体实现细节&#xff0c;具体实现细节应该依…

嵌入式开发学习--进程、线程

什么是进程 进程和程序的区别 概念 程序&#xff1a;编译好的可执行文件&#xff0c;存放在磁盘上的指令和数据的有序集合&#xff08;文件&#xff09;&#xff0c;程序是静态的&#xff0c;没有任何执行的概念。 进程&#xff1a;一个独立的可调度的任务&#xff0c;执行一…

高可靠性部署系列(3)--- ASG双机热备(HA)

高可靠性部署系列(3)--- ASG双机热备(HA) 前言网络拓扑设备选型网络规划组网需求配置思路操作步骤步骤 1 HA接口管理地址配置步骤 2 HA全局配置步骤 3 配置同步步骤 4 接口状态同步组创建结果验证前言 近期有读者留言:“因华为数通模拟器仅能支持USG6000V的防火墙,无法支…