前置知识:
[1] CentOS7安装MySQL
主从架构的作用
主从架构是保证 MySQL 高可用的重要手段。主节点会将数据同步到从节点,如果主节点宕机了,切换到从节点继续提供服务。
很多时候,系统的读的业务远远多于写的业务。这时候,可以通过主从架构来实现读写分离,从而提高系统的并发能力。
主从复制基本原理
搭建了主从架构后,从库上有一个 IO 线程,这个线程负责和主库建立一个 TCP 连接,然后请求主库传输 binlog 日志给从库,这时候主库上有一个 IO dump 线程,负责通过这个 TCP 连接把 binlog 日志传输给从库的 IO 线程。
接着从库的 IO 线程就会将获取到的 biglog 日志数据写入到本地的 relay 日志文件中去,然后从库上另外有一个 SQL 线程会读取 relay 日志里的内容,进行日志重做,把所有在主库执行过的增删改操作在从库上做一遍,进行数据还原。
主从复制的搭建
主从架构大致可以分为 3 种架构,一主多从,链式主从,多主多从。当前搭建的是一主多从架构,而且是异步复制。
1. 配置 server-id,server-uuid 和 开启 bin log
首先要保证主库和从库的 server-id,server-uuid 是不一样的,并且主库打开了 binlog功能。
查看 server-id,server-uuid 和 查看 bin log 是否开启的 SQL 如下:
show variables like '%server_id%'; # 查看server-idshow variables like '%server_uuid%'; # 查看server-uuidSHOW VARIABLES LIKE 'log_bin'; # 查看bin log 开关,off 表示关闭
修改 server-id 需要在配置文件里面进行修改,找到配置文件 my.cnf 。一般默认在 /etc/ 目录下。
找不到的话可以执行这个命令来找,可以得到 mysql 的配置文件的默认加载顺序:
mysql --help | grep 'Default options' -A 1
输出如下:
[root@localhost ~]# mysql --help | grep 'Default options' -A 1
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf
[root@localhost ~]#
在 [mysqld] 下加上如下配置:
[mysqld]
server-id=2003306 #配置 server-id
log-bin=mysql-bin # 开启 bin log
关于 server-id 的配置可以根据自身的情况来定,我这里使用的是 ip 的最后 3 位 + 端口号。
这个配置就是最简单的配置好 server-id 和开启 bin log 。但是,bin log 的开启,一般需要增加多几个配置才比较完善,完整配置如下:
[mysqld]
server-id=2003306 #配置 server-id
log-bin=mysql-bin # 开启 bin log
binlog_format = mixed #日志的格式
expire_logs_days = 7 #过期时间
日志的格式, mixed 是性能比较好,又不容易出错的选择。具体的日志格式的选择,可以看 参考[1]。
修改 server-uuid 是需要修改数据目录下的 auto.cnf 文件。这个文件在数据目录下,数据目录可以使用这条 SQL 查询出来:show variables like ‘%datadir%’; 。
我的数据目录是 /var/lib/mysql/。所以编辑命令如下: vim /var/lib/mysql/aotu.cnf 。这个文件只有 1 行,就是 server-uuid ,只需要保证主从的 server-uuid 不一致就可以了。
[auto]
server-uuid=fd01bfe8-6329-11ec-b97c-000c2959e7a8
这里我的主库的 server-uuid 是 fd01bfe8-6329-11ec-b97c-000c2959e7a8 , 从库的 server-uuid 是 fd01bfe8-6329-11ec-b97c-000c2959e7a9。
如果没有保证 server-uuid 不一致的话,从库开启 slave 模式后,然后 show slave status ; 就会看到有报错在 Last_IO_Error 字段上。
2.在主库上创建一个用于主从复制的账号
执行下面 SQL 进行创建账号,分配权限和刷新权限。注意:这些 SQL 需要在 MySQL 服务器上执行,不推荐在 Navicat 等 SQL 工具上执行,可能会出错或者有权限问题。
CREATE USER 'backup_user'@'192.168.0.%' IDENTIFIED BY 'backup_123';
GRANT replication SLAVE on *.* to 'backup_user'@'192.168.0.%' ;
FLUSH privileges;
3. 在从库上开启从库模式
在从库上执行以下 SQL ,就开启从库模式了。
-- 指定主库地址和账号密码
CHANGE MASTER TO MASTER_HOST = '192.168.0.200',
MASTER_USER = 'backup_user',MASTER_PASSWORD='backup_123';
-- 开启从库模式
START SLAVE;
-- 停止从库模式
STOP SLAVE;
-- 查看主从复制状态
SHOW SLAVE STATUS;
查看主从注释状态,主要看的是 Slave_IO_Running 和 Slave_SQL_Running ,如果都是 Yes 证明启动成功。如果不是的话,可以查看 Last_Error 列,有对应的错误说明,再根据对应的错误说明去调整。
注意:以上主从同步的过程,适合什么都没有的数据库进行主从同步;或者是可以进行停机,然后将主库的数据导到从库上去,然后开启主从同步后,再开启主库。
一般来说,数据库是不能停机的,这个问题怎么处理呢? 但是数据库一般都是有备份的,如果备份是 dump 出来的,那么可以在 dump 命令里面加上 — master-data=2 参数,输出当前备份的 bin log 文件和位置。
mysqldump -p'password' -uroot -h192.168.0.200
--skip-extended-insert --master-data=2 thirty_sec |gzip >
/home/back.sql.gz
打开 SQL 文件后,就可以看到类似 ‘ CHANGE MASTER TO MASTER_LOG_FILE=’mysql-bin.001145’, MASTER_LOG_POS=346920; ‘ 的字样了。
然后就可以在从库里面回复数据的时候,加上这两个参数,那么从库回复后,就会从bin log 对应的位置开始进行同步。
CHANGE MASTER TO MASTER_HOST = '192.168.0.200',
MASTER_USER = 'backup_user',MASTER_PASSWORD='backup_123',
MASTER_LOG_FILE='mysql-bin.001145',MASTER_LOG_POS=346920;
至此以上的搭建方式都是数据库的异步复制的方式。如果数据在写入主库后,还没来得及复制到从库就宕机了,这时候进行主备切换,数据就会丢失了。
半同步的方式搭建
同步发方式是指,数据写入到主库后,保证对应的 bing log 同步到从库后,主库的事务才算是提交成功。这样就保证了主从同步的数据不会丢失。
半同步的搭建方式有 2 种。
- 采用插件的方式
首先在 master 安装插件,并开启。
INSTALL PLUGIN rpl_semi_sync_master soname 'semisync_master.so';
SET global rpl_semi_sync_master_enabled = on;
然后在 slave 安装插件并开启。
INSTALL PLUGIN rpl_semi_sync_slave soname 'semisync_slave.so';
SET global rpl_semi_sync_slave_enabled = on;
可以使用 SHOW PLUGINS; 来查看插件的状态。
最后重启一下从库的 IO 线程就完成了。
STOP slave io_thread;
START slave io_thread;
可以在主库上使用 SHOW GLOBAL STATUS LIKE ‘%semi%’; 查看Rpl_semi_sync_master_status 如果是 ON 就证明已经开启了半复制状态。
- MySQL 5.6.5 提供的 GTID 方式
暂时看参考2, 后续补充总结。
有些问题, bin log 一定要开启 row 格式吗?
主从架构同步延迟
进行主从异步复制的时候,会产生一定的延迟。主要是因为主库是多线程写入,从库是单线程拉取 bin log 日志。主库的写入速度就会比从库的写入速度快。
可以使用 precona-toolkit 工具集里面的 pt-heartbeat 工具进行同步延迟的监控。大致原理是在主库上维护一个 heartbeat 表,有一个线程会定时去更新这个表里面的时间戳,从库也会有一个线程来监控和对比,主库的时间戳和从库的时间戳,就可以知道延迟了多久。
可以设置从库也使用多线程来进行同步,减少主从同步的延时。在从库里面设置 slave_parallel_workers > 0 并且将 slave_parellel_type 设置为 LOGICAL_CLOCK 就可以了。
如果需要强制一定要读取到立刻写入的数据的话,只能通过强制读写都从主库进行。
比较建议的方案是,使用半同步的方式来进行同步。可以保证主库宕机主从切换的情况下,数据不会丢失。再打开多线程复制来加快复制的性能。
主从架构同步异常
参考:
[1] MySQL 如何开启 binlog?binlog 三种模式的分析
[2] 基于 Gtid 的 MySQL 主从同步实践
[3] MYSQL 主从同步异常解决方案
