目录
mysql主从配置的流程大体如图:
1)master会将变动记录到二进制日志里面;
2)master有一个I/O线程将二进制日志发送到slave;
3)slave有一个I/O线程把master发送的二进制写入到relay日志里面;
4)slave有一个SQL线程,按照relay日志处理slave的数据;
环境 | mysql版本 | ip地址:端口号 |
---|---|---|
主库(master) | 5.7 | 172.16.209.100:33307 |
从库(slave) | 5.7 | 172.16.209.100:33306 |
用docker拉起两个mysql容器,步骤如下(对docker不熟悉的同学可以查看docker快速入门章节):
# 拉取mysql5.7镜像 docker pull mysql:5.7 #在home目录下创建mysql文件夹,下面创建data和conf.d文件夹 mkdir /home/mysql mkdir /home/mysql/conf.d mkdir /home/mysql/data/ # 为了目录映射 #在home目录下创建mysql文件夹,下面创建data和conf.d文件夹 mkdir /home/mysql2 mkdir /home/mysql2/conf.d mkdir /home/mysql2/data/ # 创建my.cnf配置文件(mysql1配置文件) touch /home/mysql/my.cnf # 创建my.cnf配置文件(mysql2配置文件) touch /home/mysql2/my.cnf
# 切换到home cd /home # 1.切换到mysql路径内 vim /mysql/my.cnf # mysql/my.cnf添加如下内容:(配置主库) [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 # id号 # 开启二进制日志功能,可以随便取(关键) log-bin=mysql-bin # 主库需要配以下两句 [client] # 客户端配置 default-character-set=utf8 [mysql] # mysql配置 default-character-set=utf8
# 2.切换到mysql2路径内 vim /mysql2/my.cnf # mysql2/my.cnf添加如下内容:(配置从库) [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 # 从库id号 # 开启二进制日志功能,可以随便取(关键) log-bin=mysql-slave-bin # relay_log配置中继日志 relay_log=edu-mysql-relay-bin
#启动主库容器(挂载外部目录,端口映射成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
# docker ps # 没有mysql就安装
#连接主库 mysql -h 47.102.133.190 -P 33307 -u root -p123456 #在主库创建用户并授权 ##创建test用户 create user 'test'@'%' identified by '123'; ##授权用户(任何表库,任何ip地址登录方式) grant all privileges on *.* to 'test'@'%' ; ###刷新权限 flush privileges; #查看主服务器状态(显示如下图) show master status;
mysql-bin : bin-log日志 # Position数据位置: 2128 1.从库下次写入就在该位置复制或者从头开始0位置复制进行主从同步,
# 远程连接从库 mysql -h 47.102.133.190 -P 33306 -u root -p123456 #配置详解 /* change master to master_host='MySQL主服务器IP地址', master_user='之前在MySQL主服务器上面创建的用户名', master_password='之前创建的密码', master_log_file='MySQL主服务器状态中的二进制文件名', master_log_pos='MySQL主服务器状态中的position值,0表示从头开始复制'; */ #命令如下 change master to master_host='47.102.133.190',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;
#在主库上创建数据库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 tom;
# s1.py import os # 脚本中调用django的环境 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djang333.settings') import django # 启动django django.setup() from app01.models import Book if __name__ == '__main__': # 手动方式实现读写分离: # 插入,修改,删除使用主库(default) # using('default') : 指定使用default主库写入(不写默认default) # Book.objects.using('default').create(name='金梅瓶', price=11) # 查询使用从库(db1) # using() queryset对象方法 # using('db') : 指定使用db从库查询 # res=Book.objects.using('db').filter(pk=1) # res=Book.objects.using('default').filter(pk=1) # print(res) # 自动方式(读写分离): # 插入,修改,删除使用主库(default) Book.objects.create(name='杀无赦', price=100) # 查询使用从库(db1) res = Book.objects.filter(pk=1).first() print(res.name)
# models.py from django.db import models class Book(models.Model): name = models.CharField(max_length=32) price = models.IntegerField()
# 1.在setting.py中配置 DATABASES = { # 主库 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_test', 'USER': 'root', 'PASSWORD': '123456', 'HOST': '47.102.133.190', 'PORT': 33307, }, # 从库 'db1': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_test', 'USER': 'root', 'PASSWORD': '123456', 'HOST': '47.102.133.190', 'PORT': 33306, }, } # 在setting中注册 # 注册一下 # 配置全局数据库路由 DATABASE_ROUTERS = ['app01.db_router.DataRouter'] # 以后只要是写操作,就会用default,只要是读操作自动去db1
# db_router.py # 数据库路由 class DataRouter: def db_for_read(self, model, **hints): return 'db1' def db_for_write(self, model, **hints): return 'default'
# 迁移数据库,同步 makemigrations --merge # 需要跟同事写的合并一下数据 makemigrations migrate --database=default # 将迁移记录同步到default库中 migrate --database=db1 # 将迁移记录同步到db1中
# 创建数据库db_test
makemigrations # 迁移数据库 migrate # 同步数据库
# 实现读写分离