1、概述
MySQL 的主从复制又叫 Replication、AB 复制。至少需要两个 MySQL 服务(可以是同一台机器,也可以是不同机器之间进行)。
比如A服务器做主服务器,B服务器做从服务器,在A服务器上进行数据的更新,通过 binlog 日志记录同步到B服务器上,并重新执行同步过来的 binlog 数据,从而达到两台服务器数据一致。
MySQL 数据库的主从复制方案,与使用 scp/rsync 等命令进行的文件级别复制类似,都是数据的远程传输。只不过 MySQL 的主从复制是其自带的功能,无需借助第三方工具,而且MySQL的主从复制并不是数据库磁盘上的文件直接拷贝,而是通过逻辑的 binlog 日志复制到要同步的服务器本地,然后由本地的线程读取日志里面的 SQL 语句,重新应用到 MySQL 数据库中。
2、作用
可以实时灾备,用于故障切换;
读写分离,提供查询服务,实现负载均衡;
数据热备,避免影响业务
3、原理
主节点必须启用二进制日志,记录任何修改了数据库数据的事件。从节点开启一个线程(I/O Thread)把自己扮演成 mysql 的客户端,通过 mysql 协议,请求主节点的二进制日志文件中的事件主节点启动一个线程(dump Thread),检查自己二进制日志中的事件,跟对方请求的位置对比,如果不带请求位置参数,则主节点就会从第一个日志文件中的第一个事件一个一个发送给从节点。从节点接收到主节点发送过来的数据把它放置到中继日志(Relay log)文件中。并记录该次请求到主节点的具体哪一个二进制日志文件内部的哪一个位置(主节点中的二进制文件会有多个,在后面详细讲解)。从节点启动另外一个线程(sql Thread ),把 Relay log 中的事件读取出来,并在本地再执行一次。4、注意事项
主从复制是异步的逻辑的 SQL 语句级的复制;复制时,主库有一个 I/O 线程,从库有两个线程,及 I/O 和 SQL 线程;实现主从复制的必要条件是主库要开启记录 binlog 的功能;作为复制的所有 MySQL 节点的 server-id 都不能相同;binlog 文件只记录对数据内容有更改的 SQL 语句,不记录任何查询语句5、复制中线程的作用
从节点: I/O Thread: 从 Master 节点请求二进制日志事件,并保存于中继日志中。Sql Thread: 从Relay log 中读取日志事件并在本地完成重放。 主节点: Dump Thread:为每个 Slave 的 I/O Thread 启动一个 dump 线程,用于向从节点发送二进制事件。6、主从复制配置过程
主节点:
启用二进制日志。为当前节点设置一个全局唯一的server_id。创建有复制权限的用户账号 REPLIACTION SLAVE ,REPLIATION CLIENT。
从节点:
启动中继日志。为当前节点设置一个全局唯一的server_id。使用有复制权限的用户账号连接至主节点,并启动复制线程。
7、配置演示
测试环境
Linux版本:CentOS 6.8MySQL版本:mysql-5.5.17
有很多种配置主从同步的方法,可以总结为如下的步骤:
1.在主服务器上,必须开启二进制日志机制和配置一个独立的ID
2.在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号
3.在开始复制进程前,在主服务器上记录二进制文件的位置信息
4.如果在开始复制之前,数据库中已经有数据,就必须先创建一个数据快照(可以使用mysqldump导出数据库,或者直接复制数据文件)
5.配置从服务器要连接的主服务器的IP地址和登陆授权,二进制日志文件名和位置
配置主服务器
编辑主节点的配置文件
进入MySQL数据库的配置文件f,添加如下信息
主服务器:[mysqld]port = 3306server-id = 1#要同步的数据库binlog-do-db = cloudDB01#要生成二进制日志文件 主服务器一定要开启log-bin = mysql-bin重启MySQL
创建主服务复制用户及相关权限
创建用户,每一个从服务器都需要用到一个账户名和密码来连接主服务器,可以为每一个从服务器都创建一个账户,也可以让全部服务器使用同一个账户。下面就为同一个ip网段的所有从服务器创建一个只能进行主从同步的账户。
首先登陆mysql,然后创建一个用户名为htzw,密码为123456的账户,该账户可以被192.168.67网段下的所有ip地址使用,且该账户只能进行主从同步
#创建用户,并设置用户权限mysql > grant replication slave on *.* to ‘htzw’@‘192.168.67.%’ identified by ‘123456’;
#刷新权限mysql> flush privileges;
获取二进制日志的信息并导出数据库,步骤:
首先登陆数据库,然后刷新所有的表,同时给数据库加上一把锁,阻止对数据库进行任何的写操作
mysql > flush tables with read lock;
然后执行下面的语句获取二进制日志的信息
mysql > show master status;
File的值是当前使用的二进制日志的文件名,Position是该日志里面的位置信息(不需要纠结这个究竟代表什么),记住这两个值,会在下面配置从服务器时用到。
注意:如果之前的服务器并没有配置使用二进制日志,那么使用上面的sql语句会显示空,在锁表之后,再导出数据库里的数据(如果数据库里没有数据,可以忽略这一步)
[root@localhost backup]# mysqldump -uroot -p'123456' -S /data/3306/data/mysql.sock --all-databases > /server/backup/mysql_bak.sql
如果数据量很大,可以在导出时就压缩为原来的大概三分之一
[root@localhost backup]# mysqldump -uroot -p'123456' -S /data/3306/data/mysql.sock --all-databases | gzip > /server/backup/mysql_bak.sql.gz
这时可以对数据库解锁,恢复对主数据库的操作
mysql > unlock tables;
配置从服务器
修改配置文件及数据准备首先检查从服务器上的f文件中是否已经在[mysqld]模块下配置了server-id。注意上面的server-id的值都是可以改为其他值的(建议更改为ip地址的最后一个字段),如果没有上面的配置,首先关闭mysql服务器,然后添加上去,接着重启服务器
从服务器:[mysqld]port = 3306server-id = 2#要同步的数据库binlog-do-db = cloudDB01#要生成二进制日志文件(从服务器可选)log-bin = mysql-bin重启MySQL
如果有多个从服务器上,那么每个服务器上配置的server-id都必须不一致。从服务器上没必要配置log-bin,当然也可以配置log-bin选项,因为可以在从服务器上进行数据备份和灾难恢复,或者某一天让这个从服务器变成一个主服务器
如果主服务器导出了数据,下面就导入该文件,如果从主服务器上拿过来的是压缩文件,就先解压再导入。如果主服务器没有数据,就忽略这一步
[root@localhost ~]# mysql -uroot -p'123456' -S /data/3306/data/mysql.sock < /server/backup/mysql_bak.-07-01.sql
配置同步参数
配置同步参数,登录mysql,输入如下命令
mysql> CHANGE MASTER TOMASTER_HOST='master_host_name',MASTER_PORT='master_port'MASTER_USER='replication_user_name',MASTER_PASSWORD='replication_password',MASTER_LOG_FILE='recorded_log_file_name',MASTER_LOG_POS=xxx;
启动主从同步进程
mysql > start slave;
检查状态
mysql > show slave status\G
下面的两个进程都显示YES则表示配置成功
mysql replication 中slave机器上有两个关键的进程,死一个都不行,一个是slave_sql_running,一个是Slave_IO_Running,一个负责与主机的io通信,一个负责自己的slave mysql进程。
8、主从同步技巧
主服务器第一次导入数据,如果你从其他地方拿来了要导入到主服务器中的数据,此时只要在主服务器中导入一次即可,因为这些数据会自动发送到从服务器中,在主服务器上使用命令shell > mysql -h master < other_data.sql
增加从服务器,本来已经至少有一个从服务器时(暂时命名为slave1),决定再添加其余的从服务器(slave2),此时就不需要像上面那样去操作主服务器,只要复制一个已经存在的从服务器就可以了
复制的控制相关命令:
stop salve //停止slave链路reset slave //重置slave链路start slave //开启slave链路stop master //停止master链路reset master //重置master链路start master //开启master链路
9、 主从服务器的进程查看
查看主服务器的进程
mysql > show processlist;
查看从服务器的进程
mysql > show processlist;
10、问题排查
Slave_IO_Running: NO
这是一个很常见的错误,总结起来就三个原因:
主服务器的网络不通,或者主服务器的防火墙拒绝了外部连接3306端口在配置从服务器时,输错了ip地址和密码,或者主服务器在创建用户时写错了用户名和密码在配置从服务器时,输错了主服务器的二进制日志信息
排错过程:(主服务器ip:192.168.67.140,从服务器ip:192.168.67.130)
第0步就是检查错误日志,如果不能快速排错,可以按我的步骤试试:
1.首先在从服务器上执行ping程序,确定能ping通主服务器
在从服务器上执行mysq的远程连接
[root@slave204 log]# mysql -urep -p -h 192.168.67.140 -P3306如果显示ERROR 1045 (28000): Access denied for user 'test'@'192.168.67.130' (using password: YES)
2.登陆主服务器的mysql,查看所有的用户
mysql > select user,host from mysql.user;
看看用户名是否写错,假如用户名写错了,先删除错误的用户(如用户名为test@192.168.67.%)
mysql > drop user “test@192.168.67.%”@”%”;
再重新创建用户
mysql > grant replication slave on *.* to ‘rep’@‘192.168.67.%’ identified by ‘123456’;mysql > flush privileges;
案例分析
(1)查看主服务器
mysql > show master status\G
(2)在从服务器上查看
mysql > show slave status\G
问题原因在于:发现Master_Log_File没有对应
在出现Slave_IO_Running:No的机器上进行如下操作
mysql > slave stop; mysql >CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000026', MASTER_LOG_POS=0; mysql > slave start; mysql > show slave status\G
到此问题解决!!
Slave_SQL_Running: No
解决办法如下
mysql > stop slave; mysql > SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; mysql > start slave; mysql > show slave status\G