首页 > 数据库 >mysql07--主从搭建、Django实现mysql读写分离

mysql07--主从搭建、Django实现mysql读写分离

时间:2022-09-22 15:48:02浏览次数:90  
标签:主库 mysql07 -- Django master mysql 线程 日志 从库

1 mysql--单主N从搭建

https://www.liuqingzheng.top/python/其他/02-MySQL主从搭建基于docker/

1.1 基本介绍

MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。


MySQL复制是基于主服务器在二进制日志中跟踪所有对数据库的更改。
因此要进行复制,必须在主服务器上启用二进制日志。
每个从服务器从主服务器接收主服务器已经记录到日志的数据。

 
当一个从服务器连接主服务器时,它通知主服务器在二进制日志中读取的最后一次成功更新的位置。
从服务器接收从那时起发生的任何更新,并在本机上执行相同的更新。
然后封锁并等待主服务器通知新的更新。
从服务器执行备份不会干扰主服务器,在备份过程中主服务器可以继续处理更新。

1.2 原理

1.2.1 基本原理

# 主从同步的流程或原理
  1.master会将变动记录到二进制日志(BinLog)里面
  2.master有一个I/O线程(Dump thread) 将二进制日志发送到slave
  3.slave有一个I/O线程(IO thread) 把master发送的二进制日志写入到中继日志(Relay Log)里面
  4.slave有一个SQL线程,解析中继日志中的事件,并在从库执行,保持与主库的数据一致。


# 复制中的线程
  1.主库
    Dump thread:在复制过程中,主库发送二进制日志 的线程
  2.从库
   IO thread:接受主库的二进制日志,并写入到relay log日志中 的线程
   SQL thread:读取中继日志中的事件,并执行 的线程

# 复制中的日志文件
  binlog    :主库的二进制日志 (这些记录叫做二进制日志事件,binary log events)
  Relay-log :从库的中继日志,存储请求过来的二进制日志


# 中继日志
  是连接mastert和slave的信息,它是复制的核心
  I/O线程将来自master的事件存储到中继日志中,中继日志充当缓冲
  这样master不必等待slave执行完成就可以发送下一个事件

    
# 注:
  实际生产中,读的需求  > 写的需求
  故:
    通常就是  一主多从    主库:写入数据  从库:读取数据

1.2.1 详细流程

# 同步的入口准备:
  1.从库连接主库时(change master to)
    ip port user password binlog position 会写入到master.info进行记录

  2.从库开启时(start slave) ,会启动IO线程和SQL线程



# 同步的流程:
1.从库的IO线程,读取master.info信息,获取主库信息并连接主库

2.主库接收从库的链接请求后,会生成一个准备binlog DUMP的线程,来响应从库

3.主库一旦有新的日志生成,会发送“信号”给主库的binlog dump线程,然后binlog dump线程会读取binlog日志的更新

4.通过binlog dump线程将数据传送给从库的IO线程

5.IO线程将收到的日志存储到了TCP/IP缓存

6.写入TCP/IP缓存后,立即返回ACK消息给主库,此时主库工作完成。

7.IO线程更新master.info文件、binlog文件名和postion定位

8.IO线程将缓存中的数据,存储到relay-log日志文件,此时io线程工作完成。

9.从库SQL线程读取relay-log.info文件,获取到上次执行到的relay-log的位置,作为起点

10.从库SQL线程基于从步骤9中获取到的起点,去中继日志relay-log.000001获取后续操作,在从库回放relay-log中继日志之中内从主库复制过来的数据

11.SQL线程回放完成之后,会更新relay-log.info文件,把当前操作的位置记入,作为下一次操作的起点

12.relay-log会有自动清理的功能

1.3 配置

1.3.1 配置流程

# 主从搭建主要分两种情况:
  1.主库与从库,都是新搭建
    就不需要备份主库数据,恢复到从库
    
  2.主库已存在,新配置的复制从库
    一般需要备份主库数据,恢复到从库,然后从库从备份的时间点起自动进行复制


# 主、从是新建的配置流程:
1.在主库上创建一个用于复制的账号
2.修改主库配置文件,开启主库的Binlog,并设置server-id和启动
3.修改从库配置文件并启动
4.配置主从复制
  change master to时,指定binlog为主库的二进制文件名 和 position为0 即可
5.开启主从复制


# 主库已存在的配置流程:
1.在主库上创建一个用于复制的账号
2.修改主库配置文件,开启主库的Binlog,并设置server-id和重启

3.导出主库中所有的数据,先导给从库
  # 备份数据库   全量所有数据
    mysqldump -uroot -p123456 -A -E -R --triggers --master-data=2 --single-transaction > /tmp/all.sql
    # mysqldump是逻辑备份,导出的是SQL语句
    详见:https://www.cnblogs.com/Haier123/p/15546112.html
    
  # 导入给从库
    # 拷贝给从库服务器
    scp /tmp/all.sql root@从库ip:/tmp/
    # 导入数据给从库
    mysql -uroot -p123456 < /tmp/all.sql
      
4.修改从库配置文件并启动
5.配置主从复制
6.开启主从复制

# 注:
  强调:若是第三步 导出主库数据时,主库正在运行写入 需要进行锁表处理(防止数据导出遗漏)
  # 锁表
    flush table with read lock;
    
  # 解锁
    unlock tables;

1.3.2 配置案例--主从都新搭建

# 配置搭建:正常是两台服务器,但没有 就借助docker 起两个mysql服务

# 注:
  1.通常docker起的mysql、redis服务,都需要将服务配置和数据文件 挂载到本机上
    防止容器挂掉,数据丢失。


# 1 宿主机外部 分别新建master和slave的mysql目录  用来容器外部挂载 

### 主库目录:在home目录下创建mysql文件夹,下面创建data文件夹、conf.d文件夹、my.cnf配置文件
mkdir /home/mysql
mkdir /home/mysql/conf.d
mkdir /home/mysql/data/
touch /home/mysql/my.cnf

### 从库目录
mkdir /home/mysql2
mkdir /home/mysql2/conf.d
mkdir /home/mysql2/data/
touch /home/mysql2/my.cnf


# 2 修改mysql的配置文件 vim my.cnf
### 主库的配置文件:server-id、开启binlog日志
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000

server-id=100      # 设置server_id 注意要唯一
log-bin=mysql-bin  # 开启二进制日志功能,可以随便取(关键)

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8


### 从库的配置文件:server-id、中继日志(relay_log)
                 是否开启binlog日志(log-bin)   # 取决于该从库是否还会作为其他从库的主库  若只是从库,不开启
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000

server-id=101       # 设置server_id 注意要唯一   从库连接主库 就根据这个id去查找的 
# log-bin=mysql-slave-bin   # 开启二进制日志功能,以备该Slave作为其它Slave的Master时使用
relay_log=edu-mysql-relay-bin   # relay_log配置中继日志 
read-only=true      # 开启从库 只读

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8



# 3 拉起两个mysql容器
# 启动主库容器(挂载外部目录,端口映射成33307,密码设置为123456)
docker run  -di -v /home/mysql/data/:/var/lib/mysql -v /home/mysql/conf.d:/etc/mysql/conf.d -v /home/mysql/my.cnf:/etc/mysql/my.cnf -p 33307:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
                    
# 启动从库容器(挂载外部目录,端口映射成33306,密码设置为123456)
docker run  -di -v /home/mysql2/data/:/var/lib/mysql -v /home/mysql2/conf.d:/etc/mysql/conf.d -v /home/mysql2/my.cnf:/etc/mysql/my.cnf -p 33306:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
                    
                    
                    
# 4 在主库中 创建 能复制从库 的用户 并授权
    该用户:至少有 复制从库的权限(replication slave)
    
# 连接主库
mysql -h 172.16.209.100 -P 33307 -u root -p 123456

# 创建test用户     不能是主库的root用户
create user 'test'@'%' identified by '123';
  # '%' 表示 能够在所有ip的客户端 通过该用户 登录到主库
  或允许登录的从库地址是'ip地址'   
    create user 'test'@'192.168.0.111' identified by '123';

# 授权用户
grant all privileges on *.* to 'test'@'%' ;
  # 或只授予 复制从库的权限
    grant replication slave on *.* to 'test'@'%' ;
  # 或只授予 复制到某个ip地址的从库
    grant replication slave on *.* to 'test'@'192.168.0.111';

# 刷新权限
flush privileges;

# 查看主服务器状态(显示如下图)
show master status;    # 查出binlog日志状态
  >>> 
    +---------------+----------+--------------+------------------+-------------------+
    | File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +---------------+----------+--------------+------------------+-------------------+
    | binlog.000001 |      154 |              | mysql            |                   |
    +---------------+----------+--------------+------------------+-------------------+
    # File是二进制日志文件名,Position是目前二进制日志记录到的位置。后面从库会用到 !!!



# 5 连接从库,配置连接主库
# 连接从库
mysql -h 172.16.209.100 -P 33306 -u root -p 123456

# 配置详解
/*
change master to 
master_host='MySQL主库的服务器IP', 
master_port='主库端口',
master_user='主库用于复制的用户', 
master_password='用户密码', 
master_log_file='主库二进制日志的文件名', 
master_log_pos='主库二进制日志的偏移量 position值';  
  # 从哪开始复制二进制日志(file+position)
  0: 表示从开头全部复制  当前值:表明从当前开始复制
*/

# 命令如下
change master to master_host='101.133.225.166',master_port=33307,master_user='test',master_password='123',master_log_file='mysql-bin.000003',master_log_pos=0;

# 启用从库
start slave;

# 查看从库状态(如下图)
show slave status \G;
### 这两个是yes表示配成功  
   Slave_IO_Running: Yes    # 将二进制日志 从主库同步到从库 的IO进程启动成功
   Slave_SQL_Running: Yes   # 从中继日志 回写日志 的SQL进程启动成功

    
# 6 测试
# 在主库上创建数据库test1
create database test1;
use test1;
# 创建表
create table tom (id int not null,name varchar(100)not null ,age tinyint);
# 插入数据
insert tom (id,name,age) values(1,'xxx',20),(2,'yyy',7),(3,'zzz',23);

# 在从库上查看是否同步成功
# 查看数据库
show database;
use test1;
# 查看表
show tables;
# 查看数据
select * from test1;

2 mysql--多主多从搭建

详见:https://www.cnblogs.com/Haier123/p/15546115.html

3 django操作mysql读写分离

# 0 mysql主从搭建好了

# 1 在setting中配置
DATABASES = {
    # 主库      
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'lqz1',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '101.133.225.166',
        'PORT': 33307,
    },
    # 从库
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'lqz1',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '101.133.225.166',
        'PORT': 33306,
    },
}

# 注:orm的读写 默认就是default库,故:一般主库 别名就叫 default

    
# 2 orm 创建表模型 并迁移
  # 在数据库迁移时,可以指定把哪个app的表结构迁移到哪个库 (settings中数据库的别名)
  python manage.py migrate app01 --database=default  # 不写 默认为 default


# 3 orm 操作表数据  指定使用哪个库进行操作
### 3.1 手动指定
    # 向主库写     不跟using参数  默认为default库
    res=models.Book.objects.using('default').create(name='金1梅',price=33.4)
    
    # 去从库查
    res=models.Book.objects.using('db1').all().first()
    # print(res.name)
    
    
### 3.2 自动指定  写router和配置setting 
    # 1. db_router.py中  写一个Router1类
      class Router1:
          def db_for_read(self, model, **hints):
              return 'db1'
          def db_for_write(self, model, **hints):
              return 'default'
    
    # 2.在setting中注册 DATABASE_ROUTERS
	DATABASE_ROUTERS = ['db_router.Router1',]
      
    # 注:自动指定后,以后只要是写操作就会用default,只要是读操作就会用db1


# 4 更细粒度  Router类的方法  可以指定到某个表   通常是分库分表后 使用
class Router1:
    def db_for_read(self, model, **hints):
        if model._meta.model_name == 'book':
            return 'db1'
        else:
            return 'default'

    def db_for_write(self, model, **hints):
        return 'default'

标签:主库,mysql07,--,Django,master,mysql,线程,日志,从库
From: https://www.cnblogs.com/Edmondhui/p/16719528.html

相关文章

  • message from server: "Host 'JFYL-XXXXXXXX' is not allowed to connect to this MyS
    SQLyog可以登录,但我使用springboot连接数据库发现报错,可能是数据库权限设置问题找到mysql库查看user表  更改root用户权限updateusersethost=‘%’whereuse......
  • python解释器下载与安装+配置环境变量
    一.python解释器的下载与安装......
  • js 手写日历 改变年 改变月
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"conten......
  • 一套.NET Core +WebAPI+Vue前后端分离权限框架
    今天给大家推荐一个基于.NetCore开发的企业级的前后端分离权限框架。项目简介这是基于.NetCore开发的、构建的简单、跨平台、前后端分离的框架。此项目代码清晰、层......
  • Servlet
    概述web界面具有极强的交互性,使用html写的,html具有超强的表现力,可以展现出任何你想要的界面,排版或颜色都可以有很丰富的处理,而且bs架构还有一个好处,客户端无需做任何部署......
  • tomcat server.xml标签功能详解
    1.具体说明  tomcat/conf/server.xml<!--属性说明port:指定一个端口,这个端口负责监听关闭Tomcat的请求shutdown:向以上端口发送的关闭服务器的命令字符串--><Se......
  • OA系统通用模块:用户、部门和请假(1):用户需求和故事
    根据该请假文档,完成以下1.部门管理(树形结构,增删改查)2.用户管理(依附于机构-子公司名称,增删改查、重置密码(123456)、职位等级)财务部财务1部会计部......
  • 自适应图片上的小图片缩放时等比例缩减
    用到fiex弹性布局效果:缩放时小黄圆点也跟着一起缩放   代码结构:<!--灰色背景--><divclass="boxImg"ref="cont"style="position:absolut......
  • Python 简介
    ###本简介浓缩了一些基本概念,并且随着学习会不断增加跟新### Python是一种解释型的面向对象的语言。由GuidoVanRossum于1989年发明,1991年公布。网站www.python.o......
  • map.merge() 方法
     packageutils;importlombok.AllArgsConstructor;importlombok.Data;importlombok.extern.slf4j.Slf4j;importjava.text.ParseException;importjava.text.......