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