随着应用业务数据不断的增大,数据库性能压力越来越大。此时,我们可以将数据库扩展成 主从复制模式,将 读操作和 写操作 分离开来,多台数据库分摊请求,从而减少单库的访问压力,进而应用得到优化。
MySQL 5.6
开始,主从复制有两种方式:基于日志(binlog
)和 基于 GTID
(全局事务标示符)。这里只涉及基于日志 binlog
的 主从配置。
优点
- 负载均衡–主服务器负责对数据进行 更新、删除 和 新建 等操作,而将 查询 工作落到 从库 头上
- 异地容灾备份–可以将主服务器上的数据同步到 异地从服务器 上,极大地提高了 数据安全性
- 高可用–数据库的复制功能实现了 主服务器 与 从服务器间 的数据同步,一旦主服务器出了 故障,从服务器立即担当起主服务器的角色,保障系统持续稳定运作
- 高扩展性
缺点
- 成本增加–增加了服务器成本
- 数据延迟–从库从主库复制数据肯定是会有一定的 数据延迟 的。所以当刚插入就出现查询的情况,可能查询不出来。当然如果是插入者自己查询,那么可以直接从主库中查询出来,当然这个也是需要用代码来控制的
- 写入更慢–主从复制主要是针对 读远大于写 或者对 数据备份实时性要求较高的系统中。因为 主服务器 在写中需要更多操作,而且 只有一台可以写入的 主库,所以写入的压力并不能被分散。
环境搭建
- 创建目录结构,并修改my.cnf配置文件
#注意目录权限分配,普通用户目录权限即可
# 结构如下
mysql
├── master
│ ├── conf
│ │ └── my.cnf
│ └── data
└── slaver
├── conf
│ └── my.cnf
└── data
添加Master配置内容: my.cnf
[mysqld]
# 用于标识不同的数据库服务器,而且唯一
server_id = 1
# 需要启用二进制日志
log-bin= mysql-bin
read-only=0
# 指定同步的数据库 不填则是全部
binlog-do-db=test_db
# 忽略记录二进制日志的数据库
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
添加Slave配置内容: my.cnf
[mysqld]
server_id = 2
log-bin= mysql-bin
read-only=1
# 指定同步的数据库 不填则是全部
binlog-do-db=test_db
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
2.创建容器
# 查看mysql镜像
docker search mysql
# 拉取镜像
docker pull mysql:5.7
# 创建master
docker run -p 3306:3306 --name mastermysql -e MYSQL_ROOT_PASSWORD=123456 -v ~/mysql/master/data:/var/lib/mysql -v ~/mysql/master/conf/my.cnf:/etc/mysql/my.cnf -d mysql:5.7
# 创建slave
docker run -p 3307:3306 --name slavermysql -e MYSQL_ROOT_PASSWORD=123456 -v ~/mysql/slaver/data:/var/lib/mysql -v ~/mysql/slaver/conf/my.cnf:/etc/mysql/my.cnf -d mysql:5.7
3.配置主从数据库
主数据库配置
docker exec -it mastermysql bash
mysql -u root -p123456
# 创建一个用户来同步数据
GRANT REPLICATION SLAVE ON *.* to 'slave'@'%' identified by '123456';
# 查看状态,记住File、Position的值,在Slaver中将用到
show master status;
#展示如下
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
从数据库配置
// 进入slaver容器
docker exec -it slavermysql bash
mysql -u root -p123456
//设置主库链接
mysql> change master to master_host='192.168.10.103',master_user='slave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=438,master_port=3316, master_connect_retry=30;
// 启动主从同步
mysql> start slave;
// 查看状态
mysql> show slave status;
// 查看连接信息
show slave status \G;
说明:
master_host:主库地址
master_user:主库创建的同步账号
master_password:主库创建的同步密码
master_log_file:主库产生的日志
master_log_pos:主库日志记录偏移量
master_port:主库使用的端口,默认为3306
Tip关于mysql5.7版本 **ONLY_FULL_GROUP_BY ** 问题
# 几个相关的命令
查看mysql版本命令:select version();
查看sql_model参数命令: SELECT @@GLOBAL.sql_mode; SELECT @@SESSION.sql_mode;
# 如果开启了ONLY_FULL_GROUP_BY模式,执行以下命令关闭即可
set sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
# 如果上面设置完成后依然报错,这里执行下面的SQL,将全局设置更改,然后必须关闭现有的连接,重新打开连接后查询即可
set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
关于数据备份
# 可以使用mysqldump crontab 并结合脚本方式实现
参考 https://juejin.im/post/6844903615044255757