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 {

    @Autowired
    private 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%2B8
          username: admin
          password: MySQL@3306
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave:
          url: jdbc:mysql://从节点IP:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
          username: admin
          password: MySQL@3306
          driver-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%2B8
          username: ENC(oM2ceVnn3KOTEv9Ci4yI4QKwfaSzHZpb26SWQuxlgtcMtYpbr5HYK30TT+jtI+IOsZJHqSaWhhPPlfM40rnYrw==)
          password: ENC(TvstWlvbEKqPzJrek8fx3+Si6c6OeoiZVE7Njbf+fYwjqb/Tr3v0YevMfdG8FAB32U3xda5J7AdRhAcWA0A1rg==)
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave:
          url: jdbc:mysql://从库IP:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
          username: ENC(oM2ceVnn3KOTEv9Ci4yI4QKwfaSzHZpb26SWQuxlgtcMtYpbr5HYK30TT+jtI+IOsZJHqSaWhhPPlfM40rnYrw==)
          password: ENC(TvstWlvbEKqPzJrek8fx3+Si6c6OeoiZVE7Njbf+fYwjqb/Tr3v0YevMfdG8FAB32U3xda5J7AdRhAcWA0A1rg==)
          driver-class-name: com.mysql.cj.jdbc.Driver
      public-key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL2RM3JnCjtTogh3LrwN/meyWaWpSGCn7CaYRo6spLaeAhcguhi3XQrfLa7W4LQrJTENm+yA52YJfk+mWtjyl0ECAwEAAQ==

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

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

(3)更多

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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 网络操作命令Telnet

Telnet 尽管 Telnet 已经逐渐被更安全的 SSH 协议所取代&#xff0c;但在某些特定场景下&#xff0c;如对旧系统的维护或教育目的&#xff0c;Telnet 仍然有其使用价值。本文将介绍如何在 Linux 系统中安装 Telnet 客户端&#xff0c;以及如何使用它进行远程登录。 用户使用 t…

什么是DTU和串口服务器的区别

在工业物联网的快速发展中&#xff0c;数据传输单元&#xff08;DTU&#xff09;和串口服务器作为两种关键设备&#xff0c;各自扮演着重要的角色。对于传统行业来说&#xff0c;了解它们的基本概念和区别&#xff0c;有助于更好地选择和应用这些技术&#xff0c;提升生产效率和…

Rust基本数据类型-切片

一、切片是什么&#xff0c;怎么用 1、切片是什么 切片并不是 Rust 独有的概念&#xff0c;在 Go 语言中就非常流行&#xff0c;它允许你引用集合中部分连续的元素序列&#xff0c;而不是引用整个集合。 对于字符串而言&#xff0c;切片就是对 String 类型中某一部分的引用&…

基于单片机的空气质量检测系统设计

摘要:随着社会经济的不断发展,人们的生活水平日益提高,健康与养生成为了全民关注的热点话题,空气质量地不断下降也引起了社会的广泛关注,如何了解家居内空气质量的情况也成了亟需解决的问题。在此背景下,本文针对室内空气的质量问题设计了基于单片机的空气质量检测系统,…

Mysql个人总结

前言 又来水字数啦&#xff0c;这次主要讲一下MySQL的常用概念&#xff0c;难点的就必须上项目讲解了&#xff0c;而且比较基础面试基本都会问一些&#xff0c;用的话&#xff0c;不少优化都从这里入手 操作数据库 1、创建数据库 CREATE DATABASE [IF NOT EXISTS] 数据库名;…

【AI相关】《这就是ChatGPT》读书笔记

《这就是ChatGPT》 斯蒂芬沃尔弗拉姆 这本书用了两天就一口气读完了&#xff0c;通篇读完后&#xff0c;这本书主要是介绍了ChatGPT怎么能做到生成内容的一些背后的原理逻辑&#xff0c;总结一下这本书是ChatGPT通过大量的数据&#xff08;这些数据来自网络、书籍等等类似于数据…

Linux多进程(二)进程通信方式三 共享内存

共享内存提供了一个在多个进程间共享数据的方式&#xff0c;它们可以直接访问同一块内存区域&#xff0c;因此比使用管道或消息队列等通信机制更高效。在多进程程序中&#xff0c;共享内存通常与信号量一起使用&#xff0c;以确保对共享内存的访问是线程安全的。 一、打开/创建…

2024年达索系统智能制造核心合作伙伴会议圆满成功

2024年4月23日&#xff0c;达索系统在上海雅乐万豪侯爵酒店举办“2024年达索系统智能制造核心合作伙伴会议”&#xff0c;作为达索系统合作伙伴的百世慧也应邀出席了本次会议&#xff0c;并荣获“2023年度最佳销售业绩奖”&#xff0c;总经理冉恒奎先生还受邀在会上做出了精彩分…

电磁兼容(EMC):静电放电(ESD)抗扰度试验深度解读(八)

目录 1. 第一步 确定电磁环境 2. 第二步 确认设备工作状态 3. 第三步 制定试验计划 4. 间接施加的放电 4.1 水平耦合板 4.2 垂直耦合板 静电抗扰度的试验测试细节对测试结果影响比较大&#xff0c;本文详细介绍静电抗扰度试验的测试程序和注意事项。 1. 第一步 确定电磁…

Vision Pro“裸眼上车”,商汤绝影全新舱内3D交互亮相

2023年&#xff0c;Apple Vision Pro的横空出世让人们领略到了3D交互的魅力&#xff0c;商汤绝影通过深厚的技术研发实力和高效的创新迭代效率&#xff0c;带来两大全新座舱3D交互&#xff1a;3D Gaze高精视线交互和3D动态手势交互。 作为全球首创的能够通过视线定位与屏幕图标…

CST Studio初级教程 一

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

人工智能技术应用实训室解决方案

一、背景与意义 人工智能&#xff0c;作为新兴的技术科学领域&#xff0c;致力于模拟、延伸和扩展人类智能&#xff0c;其涵盖范围广泛&#xff0c;包括机器人技术、语言识别、图像识别、自然语言处理及专家系统等多元化领域。实际应用层面&#xff0c;人工智能已渗透到机器视…

【初阶数据结构】——循环队列

文章目录 1. 什么是循环队列&#xff1f;2. 结构的选择&#xff1a;数组 or 链表&#xff1f;链表结构分析数组结构分析判空判满入数据出数据取队头队尾元素 3. 代码实现&#xff08;数组结构&#xff09;C语言版本C版本 这篇文章我们来学习一下如何实现循环队列 那力扣上呢有一…

应用层协议 -- HTTPS 协议

目录 一、了解 HTTPS 协议 1、升级版的 HTTP 协议 2、理解“加密” 二、对称加密 1、理解对称加密 2、对称加密存在的问题 三、非对称加密 1、理解非对称加密 2、中间人攻击 3、CA 证书和数字签名 四、总结 一、了解 HTTPS 协议 1、升级版的 HTTP 协议 HTTPS 也是…

prompt提示词:AI英语词典,让AI教你学英语,通过AI实现一个网易有道英语词典

目录 英语词典提问技巧效果图&#xff1a;提示词&#xff1a; 英语词典提问技巧 随着AI工具的出现&#xff0c;学英语也可以变得很简单&#xff0c;大家可以直接通过AI 来帮助自己&#xff0c;提高记忆单词的效率&#xff0c;都可以不需要网易有道词典了&#xff0c;今天我教大…

Grid 布局

文章目录 容器属性display 属性grid-template-columns 和 grid-template-rows 属性row-gap、column-gap、gap 属性grid-template-areas 属性grid-auto-flow 属性justify-items、align-items、place-items 属性justify-content、align-content、place-content 属性grid-auto-col…

AI图书推荐:AI驱动的图书写作工作流—从想法构思到变现

《AI驱动的图书写作工作流—从想法到变现》&#xff08;AI-Driven Book Creation: From Concept to Cash&#xff09;是Martynas Zaloga倾力打造的一本实用指南&#xff0c;它巧妙地将写作艺术与人工智能前沿技术相结合。此书不仅揭示了AI在图书出版领域的无限潜力&#xff0c;…

Delphi 的Show和ShowModal

Show没有返回值是一个过程&#xff0c;焦点可以不在当前窗体&#xff1b; 用法新建一个子窗体&#xff1a; 主窗体&#xff1a; 调用&#xff0c;引用子窗体的单元 调用 showmodal是一个函数有返回值&#xff0c;窗体的处理结果&#xff0c;且只能聚焦到当前窗体 效果都能展示…

echarts实现云台控制按钮效果,方向按钮

效果图 代码 option {color: [#bfbfbf],tooltip: {show: false},series: [{name: ,type: pie,radius: [40%, 70%],avoidLabelOverlap: true,itemStyle: {// borderRadius: 10,borderColor: #fff,borderWidth: 2},label: {show: true,position: inside,fontSize: 36,color: #f…

CST初级教程 二

本教程将讲解CST Studio的视窗操控的基本操作. 3D视窗的快捷操作 动态放大与缩小&#xff08;Dynamic Zoom&#xff09; 将鼠标指针移动到CST Studio图形视窗中&#xff0c;向上滚动鼠标滚轮&#xff0c;可动太放大图形视窗中的显示内容&#xff0c;向下滚动鼠标滚轮即可动态缩…