目前mysql主要支持的两种复制方式
1.传统方式:
基于主库的bin-log将日志事件和事件位置复制到从库,从库再加以应用来达到主从同步的目的。
2.Gtid方式(MySQL>=5.7推荐使用):
基于GTID的复制中,从库会告知主库已经执行的事务的GTID的值,然后主库会将所有未执行的事务的GTID的列表返回给从库,并且可以保证同一个事务只在指定的从库执行一次。
1、基于二进制日志的传统方式
1、大致原理
我们在MySQL中配置了主从之后,只要我们对Master节点进行了写操作,这个操作将会被保存到MySQL的binary-log(bin-log)日志当中,当slave连接到master的时候,master机器会为slave开启binlog dump线程。当master 的 binlog发生变化的时候,Master的dump线程会通知slave,并将相应的binlog内容发送给Slave。而Slave节点在主从同步开启的时候,会创建两个线程,一个I/O线程,一个SQL线程。
I/O线程:该线程链接到master机器,master机器的binlog发送到slave的时候,IO线程会将该日志内容写在本地的中继日志(Relay log)中。
SQL线程:该线程读取中继日志中的内容,并且根据中继日志中的内容对Slave数据库做相应的操作。
可能造成的问题:在写请求相当多的情况下,可能会造成Slave数据和Master数据不一致的情况,这是因为日志传输过程中的短暂延迟、或者写命令较多,系统速度不匹配造成的。
这大致就是MySQL主从同步的原理,真正在其中起到作用的实际上就是这两个日志文件,binlog和中继日志(Relay log)。
2、实现步骤
主库配置
1、编辑/etc/my.cnf文件,新增(修改)server-id=1,这个server-id主库和各个从库不能相同。
2、在主库上创建用于数据同步的账户CREATE USER 'datacopy'@'192.168.169.%' IDENTIFIED BY 'admin123';
GRANT REPLICATION SLAVE ON *.* TO 'datacopy'@'192.168.169.%';
3、刷新权限FLUSH PRIVILEGES;
4、查看主库状态show master status;
从库配置
1、编辑/etc/my.cnf文件,新增(修改)server-id=2
2、执行同步语句,并启动slave
change master to master_host='192.168.169.147',master_user='datacopy',master_password='admin123',master_log_file='mysql-bin.000011',master_log_pos=154;
192.168.169.147是主库的IP地址。后面俩是主库的binlog日志文件名和日志偏移量。
3、查看slave状态show slave status\G;
测试验证
在主库添加测试数据
从库也新增一条一模一样的数据
3、主从库不同步1236错误
有的时候出现主从机不同步的情况,数据库服务器断电、挂掉等会有这个风险。
从二进制日志中的错误: Last_IO_Error:从二进制日志中读取数据时,主机出现致命错误1236:“在二进制日志索引文件中找不到第一个日志文件名”
详细日志
解决方法:
1.首先停止从库同步:stop slave;
2.主日志:刷新日志 flush logs;
3.查看主库状态,显示主状态;
4.返回从库中,执行命令,使日志文件和位置对应主库:
将MASTER更改为MASTER_LOG_FILE ='log-bin.000011',MASTER_LOG_POS = 154;
5.最后,启动从库:slave start;
注意点:如果要更改从库的同步日志位置,如change master to master_host='192.168.169.153',master_user='datacopy',master_password='admin123',master_log_file='mysql-bin.000012',master_log_pos=579;一定要把原来的slave io_thread停掉再修改否则会报3021的错误ERROR 3021 (HY000): This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first。
(1)stop slave io_thread;停止io线程
(2)执行更改
(3)start slave;重启slave线程