1. 基本介绍
MySQL 内建的复制功能是构建大型,高性能应用程序的基础。将 MySQL 的 数亿分布到到多个系统上去,这种分步的机制,是通过将 MySQL 的某一台主机的数据复制到其它主机( Slave )上,并重新执行一遍来实现的。复制过程中一个服务器充当服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置,从服务器接收从那时起发生的任何更新,然后封锁等等主服务器通知新的更新。
请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对服务器上的表所进行的更新之间的冲突
2. MySQL支持的复制类型
基于语句的复制。 在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对服务器上的表所进行的更新之间的冲突,配置:binlog_format = 'STATEMENT'
基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍,从 MySQL 5.0开始支持,配置:binlog_format = 'ROW'
混合类型的复制。默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制,配置:binlog_format = 'MIXED'
3. mysql复制解决的问题
数据分布
负载平衡
备份
高可用性和容错行
4. 复制是如何工作的
可以简化为三个步骤(如下图):
Master 将改变记录到二进制日志中。
Slave 将 Master 的二进制日志拷贝到它的中继日志( Relay_log )
Slave 重做中继日志中的事件,将改变反映它自己的数据
说明:
Master 记录二进制的日志。在每个事务更新数据之前,Master 在二进制日志记录这些改变。 MySQL 将事务日志的写入二进制日志,及时事务中的语句都市交叉执行的。在事件写入二进制日志完成后,Master 通知存储引擎提交事务。
Slave 将 Master 的 Binary log 拷贝到它自己的中继日志。首先 Slave 开始一个工作线程--I/O线程。I/O 线程在 Master 上打开一个连接,然后开始从二进制日志中读取事件,如果已经连上 Master,它会并等待master产生新的事件。I/O线程就这些事件写入中继日志。
SQL Slave Thread ( SQL从线程)处理该过程的最后一步。SQL纯种从中继日志读取事件,并重放其中的事件而更新 Slave 的数据。使其它与 Master 中的数据保持一致。只要该线程与 I/O 线程保持一致,中继日志通常会位于 OS 的缓存中,所以中继日志的开销很小。
此处,在 Master 中也有一个工作线程,和其他 MySQL 的连接一样,Slave 在 Master 中打开一个连接也会使得 Master 开始一个线程。复制过程有一个很重要的限制---复制在 Slave 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作。
5. 复制常用类型
5.1 复制的常用体系结构基本原则
每个 Slave 只能有一个 Master;
每个 Slave 只能有一个唯一的服务器ID;
每个 Master 可以有很多 Slave;
如果你设置了 log_slave_updates,Slave 可以是其他 Slave 的 Master,从而扩散 Master 的更新
MySQL 不支持多主服务器复制---即一个 Slave 可以有多个 Master,但是,通过一些简单的组合,我们却可以建立灵活而强大的复制体系结构。
5.2 一主多从复制架构
场景:在主库读取请求压力非常大的场景下,可以通过配置一主多从复制架构实现读写分离,把大量对实时性要求不是特别高的读请求通过负载均衡到多个从库上,降低主库的读取压力。在主库出现异常宕机的情况下,可以把一个从库切换为主库继续提供服务;
建议:
当 Slave 增加到一定数量时,Slave 对 Master 的负载以及网络带宽都会成为一个严重的问题。
不同的 Slave 扮演不同的作用(例如使用不同的索引,或者不同的存储引擎)
用一个 Slave 作为备用 Master,只进行复制
用一个远程的 Slave,用于灾难恢复。
5.3 多级复制架构
场景:一主多从的架构能够解决大部分读请求压力特别大的场景需求,但主库的I/O压力和网络压力会随着从库的增加而增长,而使用多级复制架构就可以解决一主多从场景下,主库额外的I/O和网络压力。 但要注意的是,多级复制场景下主库的数据是经历两次才到达读取的从库,期间的延时比一主多从复制场景下只经历一次复制的要大。
建议:
可能存在延时较长的风险
这种方案可以与第三方软件结合使用,例如Slave+LVS+Keepalived 实现高可用。
5.4 双主复制/Dual Master架构
场景:双主/Dual Master架构适用于写压力比较大的场景,或者DBA做维护需要主从切换的场景,通过双主/Dual master架构避免了重复搭建从库的麻烦。
建议:
最大问题就是更新冲突。
可以采用MySQL Cluster,以及将Cluster和Replication结合起来,可以建立强大的高性能的数据库平台。
二、mysql主从配置
1.基础环境配置
数据库版本: mysql 5.5.48 ( Slave 版本可以大于或者等于 Maste r版本)
操作系统: CentOS 6.7 x86_64 mininal
IP地址:192.168.5.5 ( Master ) 192.168.5.9 ( Slave )
2.创建复制账号
在 Master 的数据库中建立一个复制账户,每个 Slave 使用该账户连接 Master 进行复制,需要 replication slave 和replication client 权限,Master 的连接信息会存储在文本文件 master.info 文件中。(master.info文件在 Slave 的数据目录中)
mysql>GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.5.9' IDENTIFIED BY '211212';
mysql>flush privileges;
说明:创建了一个用户名为 replication 的用户,密码为 211212,只允许在 192.168.5.9 这个 Slave 上登录。
3.拷贝数据
如果是新安装的 MySQL 主从服务器,这一步不需要。如果 Master 之前有数据,需要把 Master 的数据导出并还原到 Slave 上,要保证 Master 和 Slave 服务器中的数据是一样的。建议导出 Master 库的时候进行锁表,导完后再解锁。
#在mysql-master上执行
[root@master ~]# mysql -u root -p211212
mysql>flush tables with read lock;
[root@master ~]# mysqldump --all-databases -uroot -p211212 > all_databases.sql
[root@master ~]# mysql -uroot -p211212
mysql> unlock tables;
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | vdevops | | wh-test | +--------------------+ 5 rows in set (0.00 sec)
[root@master ~]# scp all_databases.sql root@192.168.5.9:/root
#在mysql-slave 执行
[root@minion ~]# mysql -uroot -p211212 -hlocalhost -P3306 --default-character-set=utf8 < all_databases.sql
或者 mysql -uroot -p211212
mysql>source /root/all_databases.sql;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| vdevops |
| wh-test |
+--------------------+
5 rows in set (0.04 sec)
设置主从同步前,保证master和slave的数据一致。
4.Master 服务器配置:
修改配置都需要修改 MySQL 的数据库配置文件,默认是 /etc/my.cnf
4.1 开启二进制日志
log-bin=mysql-bin 改成log-bin=/var/log/mysql/master-bin
增加 binlog_format=mixed
server-id = 1
expire_logs_days = 10
binlog-do-db = vdevops #需要记录进制日志的数据库.如果有多个数据库可用逗号分隔,或者使用多个binlog-do-db选项
binlog-ignore-db = mysql #不需要记录进制日志的数据库.如果有多个数据库可用逗号分隔,或者使用多个binlog-do-db选项
replicate-ignore-db = mysql,information_schema #不需要同步的数据库.如果有多个数据库可用逗号分隔,或者使用多个replicate-ignore-db选项
slave-skip-errors = all #过滤掉一些没啥大问题的错误
4.2 取消 server-id 的注释
将 server-id=1 前面的注释去掉,如果没有,则手动添加到 mysqld 下面。
必须要配置 server-id ,server-id 的值不能和 Slave 是一样的。
4.3 设置需要同步的数据库
在 [mysqld] 下面添加 binlog-do-db=vdevops
说明:binlog-ignore-db=test 表示不同步 test 数据库,如果有多个数据库,需要多写几行。
4.4 创建二进制日志目录,授权,重启 MySQL
#mkdir -p /data/mysql/log
chown mysql.mysql -R /data/mysql/log
[root@master mysql]# /etc/init.d/mysql restart
4.5 查看 Master 状态
mysql > show master status;
记录下 File 和 Postition,下面配置 Slave 的时候需要用。
mysql> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 | 107 | vdevops | mysql |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
#File master-bin.000001
#Position 107
5.Slave 服务器配置
修改配置都需要修改 MySQL 的数据库配置文件,默认是 /etc/my.cnf
5.1 修改 server-id 和开启中继日志
将 server-id=1 改成 server-id=2
relay-log=/data/mysql/log/relay-log
5.2 创建中继日志,授权以及重启
mkdir -p /data/mysql/log
chown mysql.mysql -R /data/mysql/log
/etc/init.d/mysql restart
5.3 查看中继日志启动状态
mysql>show global variables like '%relay%';
5.4 连接 Master 服务器
mysql>change master to master_host='192.168.5.5',master_user='replication',master_password='211212',master_log_file='master-bin.000001',master_log_pos=107;
选项:
master_host:Master 服务器IP
master_user:Master 服务器授权用户,也就是 Master 前面创建的那个用户
master_password:Master 服务器授权用户对应的密码
master_log_file:Master binlog 文件名
master_log_pos:Master binlog 文件中的 Postion 值
更多的选项可以看:https://dev.mysql.com/doc/refman/5.7/en/change-master-to.html
说明:使用刚刚在 Master 创建的用户连接,log_file 和 log_pos 就是使用刚刚在 Master 上执行 show master status; 执行出来的结果中的File和Position
5.5 手动启动复制线程
mysql> start slave;
5.6 查看主从状态
mysql>show slave status G;
说明:如果 Last_SQL_Error 没有错误提示以及 Salve 中的 Exec_Master_Log_Pos 值和 Master 中的 show master status; 中的 Postition 值是一样的,这样的话,MySQL 主从复制应该是成功的。
# Slave_IO_Running: Connecting
# Slave_SQL_Running: Yes
如果出现:Connecting可能是File值改变导致的,因为在master上面修改配置文件重启之后,shou master status;master bin-log参数初始值已经改变。 解决:
1、网络不通
2、密码不对
3、pos不对
4、主机防火墙未关闭 #本人这个次错误就是这个原因,有点傻 .登录master,先把master锁表,flsuh tables with read lock;然后show master status;得到最新的File文件值和Position值,然后登录slave,stop slave;重新连接master: change master to master_host='192.168.5.5',master_user='replication',master_password='211212',master_log_file='master-bin.000005',master_log_pos=107; 切换master,unlock tables; #service iptables stop #到此,登录slave,show slave status G
能看到SLAVE_IO和SLAVE_SQL两个进程已经成功运行。
6. 测试
在 Master 数据库中执行sql语句操作,观察 Slave 是否同步,如果同步则说明配置成功。
登录master:
mysql -u root -p211212
mysql>use vdevops;
mysql>create table master_test(id int(4) not null,type char(20) not null);
mysql> insert into master_test values (001,'vdevops');
登录slave,查看数据是否已经同步
mysql -u root -p211212
mysql>use vdevops;
mysql> select * from master_test;
+----+---------+
| id | type |
+----+---------+
| 1 | vdevops |
+----+---------+
1 row in set (0.00 sec)
#可以进行删表操作查看主从同步变化
7. 注意事项
主库和从库的数据库名必须相同;
主库和从库的复制可以精确到表,但是在需要更改主库或从库的数据结构时需要立刻重启slave;
不能在mysql配置文件里直接写入master的配置信息,需要用change master命令来完成;
指定replicate_do_db必须在my.cnf里配置,不能用change master命令来完成;
如果不及时清理,日积月累二进制日志文件可能会把磁盘空间占满,可以在配置文件里加上expire_logs_days=7,只保留最近7天的日志,建议当slave不再使用时,通过reset slave来取消relaylog;
写一个监控脚本,用来监控 Slave 中的两个"yes",如果只有一个"yes"或者零个,就表明主从有问题。
三、MySQL 主从一致性检查
1.介绍
主从一致性主要是通过 Percona-Toolkit 这个工具来实现的,Percona Toolkit 是一组高级的命令行工具,用来管理 MySQL 和系统任务,主要功能包括:
验证主节点和复制数据的一致性
有效的对记录进行归档
找出重复的索引
总结 MySQL 服务器
从日志和 tcpdump 中分析查询
问题发生时收集重要的系统信息。
现在,使用这个工具来完成一致性检查和数据同步。
官网是:https://www.percona.com/software/mysql-tools/percona-toolkit
2.安装 Percona-Toolkit 工具
安装的方式有多种,可以编译安装,也可以通过包管理器安装,为了方便,直接下载 rpm 包,然后yum进行安装。
文件下载地址:https://www.percona.com/doc/percona-toolkit/2.2/installation.html
wget percona.com/get/percona-toolkit.rpm
yum install percona-toolkit.rpm -y
或者
wget percona.com/get/percona-toolkit.tar.gz
tar zxvf percona-toolkit.tar.gz && cd percona-toolkit
3.一致性检查
3.1 注意点:
需要创建一个既能登录主库,也能登录从库,而且还能同步数据库的帐号。
只能指定一个host,必须为主库的IP
在检查时会向表加S锁
运行之前需要从库的同步IO和SQL进程是YES状态
3.2 创建检查帐号
mysql>grant select,process,super,replication slave on *.* to 'mysql_check'@'x.x.x.x' identified by '123456';
mysql>flush privileges;
3.3 执行检测(在master上操作)
pt-table-checksum --nocheck-replication-filters --databases=dy_qqopen --replicate=test.checksums --create-replicate-table --host=192.168.5.5 --port 3306 -umysql_check -pLooking_s123 --recursion-method=hosts
参数说明:
--nocheck-replication: 不检查复制过滤器,建议启动。后面可以用--databases来指定需要检查的数据库。
--databases:指定需要被检查的数据库,多个则用逗号隔开
--tables:指定需要被检查的标,多个用逗号隔开。
--replicate:把checksum的信息写入到指定表中,建议直接写到被检查的数据库当中。
--create-replicate-table:创建存放检查信息的数据表,第一次运行需要加,以后就不需要添加了。
--recursion-method:查找 Slave 的方式,有三种, processlist, dsn, hosts
h:Master地址
u:mysql的检测用户的用户名
p:mysql检测用户的密码
P:3306,mysql的端口号
执行结果:
参数说明:
TS: 完成检查的时间
ERRORS:检查时发生错误和警告的数量
DIFFS:0 表示一致,1 表示不一致,当指定 --no-replicate-check 时,会一直为0,当指定 --replicate-check-onley 则会显示不同的信息
ROWS:表的行数。
CHUNKS:被划分到表中的块的数目
SKIPPED:由于错误或警告过大,则跳过块的数目。
TIME:执行的时间。
TABLES:被检查的表名
说明:如果出现不一致的情况,就需要进行修复了。
3.4 命令错误
问题1: 执行命令时提示 "Diffs cannot be detected because no slaves were found. Please read the --recursion-method documentation for information."错误
解决方法: 在从服务器的 /etc/my.cnf 配置文件中添加两行,report_host=192.168.5.9(slave_ip) report_port=3306(slave_port)。然后重启 MySQL 服务
4. 不一致数据修复
4.1 介绍
使用 pt-table-sync 这个命令来修复。 pt-table-sync 命令介绍:高效的同步 MySQL 表之间的数据,他可以做单向和双向的表数据。也可以同步单个表,也可以同步整个库。它不同步表结构、索引、或任何其他模式对象。所以在修复一致性之前需要保证他们表存在。
4.2 修复不一致的数据
pt-table-sync --print --user=mysql_check --password=Looking_s123 h=192.168.5.5,D=dy_qqopen,t=qq_task h=192.168.5.9
参数说明:
--print:打印出修复语句,如果需要修复,将 --print 改成 --execute,会直接执行修复语句,但是建议先使用 print 看一下修复语句,以保证不会出错。
--user:MySQL 检测用户的用户名
--password:MySQL 检测用户的密码
D:目标数据库
t:数据表
h:两个h,第一次出现的是 Master 的 IP ,第二次出现的是 Slave 的地址。
四、MySQL 主从错误处理
1. 说明:
解决和处理主从错误这个是最重要的,比配置更更要。提高处理问题的能力,要熟悉原理,多处理积累,多学习其他网友的处理方式。出现错误都会在 Last_SQL_Error 中显示错误,一般根据错误提示进行处理,如果不太清楚,可以谷歌查询一下,不过操作完之后,同步正常后,一定要核对一下数据是否一致。