介绍
MySql主从一般1主多从,当然MySql5.7开始多主一从,还有双主复制、级联复制,这里暂时不说,现在之说1主多从,利用的是MySql的replication来保证数据一致,但是必然会有延迟、不一致性,使用PCX集群可以保证一致.
其实就是把主库的binlog文件传给从库的relaylog,然后sql读取同步。
从节点I/O线程
当从节点上执行`start slave`命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中。
从节点SQL线程
SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。
开始搭建
mysql的配置
在多台服务器上安装好MySql后,修改my.cnf ,不知道位置可以whereis my.cnf 或者 whereis mysql 查看,修改完记得service mysql restart 或者systemctl mysql restart 重启服务,还有show global variables; 可以查看mysql的所有配置信息。
首先修改主库的my.cnf,加入以下两行
log-bin=mysql-bin //[必须]启用二进制日志
server-id=1 //[必须]服务器标识ID,每台服务器唯一
然后是从库的my.cnf,注意:service-id每台服务器都不可一样 ,一般主库为1,从库往后排
log-bin=mysql-bin //[必须]启用二进制日志
server-id=2 //[必须]服务器标识ID,每台服务器唯一
还有以下配置,看各人需要,配置同步哪些表
# 不同步哪些数据库
binlog-ignore-db = mysql
binlog-ignore-db = test
binlog-ignore-db = information_schema
# 只同步哪些数据库,除此之外,其他不同步
binlog-do-db = order
然后进入主库的mysql,mysql -uroot -p 进入后执行命令,修改可以被任何客户端连接 ,mysql_native_password 是身份验证插件,记得一定要用这个,MySql8.0开始默认为caching_sha2_password , 从库会连不上提示错误的,在mysql库的user表里可以看到用户所使用的身份验证插件。
mysql>ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '密码';
mysql>flush privileges; #刷新权限
注意:上面我是直接用的root用户作为从库连接凭证,最好还是新建个从库专门用的账户,如下
mysql>CREATE USER '用户名'@'%' IDENTIFIED BY '密码'; #创建用户
mysql>GRANT REPLICATION SLAVE ON *.* TO '用户名'@'%'; #分配REPLICATION(主从复制)权限
mysql>flush privileges; #刷新权限
账户创建完之后,然后在主库中再执行 show master status; 查看数据库状态 ,记住这个File 和Position ,后面从库要用到
然后进入从库的MySql,执行以下命令,修改x.x.x.x为主库IP,user,password为主库用户名和密码,log_file和log_pos就是上图的这个File和Position
mysql>change master to
master_host='x.x.x.x',
master_user='root',
master_log_file='mysql-bin.000004',
master_log_pos=1602,
master_port=3306,
master_password='123456';
执行完之后,执行 start slave; 启动从服务器复制功能,如果配置错了,执行 stop slave; 再如上配置下,再 start slave; 即可
执行完之后,在从库中执行 show slave status\G; 可以查看主从连接状态,只要Slave IO Running 和Slave SQL Running 都为Yes 就正常,还有前面的Slave_IO_State ,对应的信息显示的是Waiting for master to send event...
这个时候就已经完成了,可以去连接主库的mysql去创建表和字段,这个时候再去从库看就可以发现,已经同步过来了(可能有一点延时)
Docker下安装MySQL
简单粗暴,直接上docker-compose.yml配置,如下,主要注意的是volumes 配置,这个是使用主机 的目录来存放数据和日志,还有使用主机 的my.cnf配置文件,格式如下
volumes:
- 主机路径:容器路径
应该注意到我下面yml配置中用的是./ ,意思是docker-compose.yml 所在的当前位置下的文件夹和文件,如图
这些用到的目录和配置文件要提前新建好,然后将一下代码保存为docker-compose.yml ,放在如上图位置
version: '3'
services:
mysqlMaster: #容器名称
image: mysql:latest #镜像名称
networks: #所用网络
- backend
environment: #环境变量
- TZ=Asia/Shanghai #时区
- MYSQL_ROOT_PASSWORD=123456
volumes: #目录/文件映射 主机路径:容器路径
- ./data/master:/var/lib/mysql
- ./log/master:/var/log/mysql
- ./config/master.cnf:/etc/my.cnf
deploy:
replicas: 1 #工作节点上运行的任务数
restart_policy: #重启策略
condition: any
resources:
limits: #资源限制
cpus: "0.2"
memory: 512M
ports: #外网:容器 端口映射
- 33060:3306
mysqlSlave1:
image: mysql:latest
networks:
- backend
environment:
- TZ=Asia/Shanghai #时区
- MYSQL_ROOT_PASSWORD=123456
volumes:
- ./data/slave1:/var/lib/mysql
- ./log/slave1:/var/log/mysql
- ./config/slave1.cnf:/etc/my.cnf
deploy:
replicas: 1
restart_policy:
condition: any
resources:
limits:
cpus: "0.2"
memory: 384M
ports:
- 33061:3306
mysqlSlave2:
image: mysql:latest
networks:
- backend
environment:
- TZ=Asia/Shanghai #时区
- MYSQL_ROOT_PASSWORD=123456
volumes:
- ./data/slave2:/var/lib/mysql
- ./log/slave2:/var/log/mysql
- ./config/slave2.cnf:/etc/my.cnf
deploy:
replicas: 1
restart_policy:
condition: any
resources:
limits:
cpus: "0.2"
memory: 384M
ports:
- 33062:3306
networks:
backend:
然后在docker-compose.yml所在目录执行以下命令,创建并运行容器
docker-compose up -d
下面我放一下master的my.cnf配置,slave的my.cnf也只是改下server-id 参数就行
[mysqld]
log-bin=mysql-bin
server-id=1
character-set-server=utf8
datadir=/var/lib/mysql
innodb_buffer_pool_size = 256M
innodb_use_native_aio = 0
key_buffer_size = 128M
max_allowed_packet = 486M
myisam_sort_buffer_size = 128M
net_buffer_length = 2K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
skip-external-locking
skip-name-resolve
socket=/var/lib/mysql/mysql.sock
sort_buffer_size = 64K
table_open_cache = 256
thread_stack = 240K
user=mysql
[mysqld_safe]
log-error=/var/log/mysql/mysqld.log
pid-file=/var/lib/mysql/mysqld.pid
docker run命令版
docker run -p 33066:3306 --name mysql-master --net=mysql_backend \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /home/docker/mysql/data/master:/var/lib/mysql \
-v /home/docker/mysql/config/master.cnf:/etc/my.cnf -d mysql:latest
...省略
踩坑跳坑
1.容器是跑起来了,但是发现mysql没使用主机的my.cnf文件,而是使用的自己默认的my.cnf,于是查看日志发现有个warning: can't allow writable /config/slave2.cnf 什么的,意思就是容器如果使用主机的这个mysql配置文件,不能为可写,于是权限修改为444 ,都只能读,然后重启容器,mysql配置生效。
2.从库执行过change master...和start slave;命令后,执行show slave status;发现有问题,Slave_IO_State 显示:Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection ,关键字就是这个 caching_sha2_password ,mysql8.0默认的就是这个,网上搜寻一下,也就是说把它换成mysql_native_password ,代码如下
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '密码';
FLUSH PRIVILEGES;
3.还有一个网上看到的,防火墙问题,Slave_IO_Running: Connecting # 出现错误,IO线程处于正在连接状态,关掉主从的防火墙即可
4.注意检查账号权限,在主库新建过账号,记得主库中mysql -uroot -p 连接执行select什么的检查下,本文使用的直接是root偷懒了,安全起见使用特定用户授予REPLICATION 权限,用于从库的连接。
Comments | 2 条评论
博主 blue_hr
这也仅仅是mysql主从部署吧,没有读写分离的实现呀
博主 loneking
@blue_hr 标题改了,没有用proxy中间件,可以用mycat,atlas,tddl等等实现,
因为我之前在java里用注解去设定不同业务代码使用的数据源,实现的读写分离。