Mysql主从复制原理解析和技术难点解决
一、原理
mysql的主从复制原理相对读写分离原理较为简单,主要是主从日志文件来考虑,后续的出现的问题也大多是日志文件问题的解决;
首先大概说一下主从复制的原理:
mysql服务器在公司中充当着非常重要的角色,而且如果对于数据库毁坏将会对公司的服务器运作产生非常致命的影响。具体来说,主服务器和从服务器实现复制是靠进程来进行传输,分为两个进程,主要是I/O进程和SQL进程;I/O进程是实现主从服务器的相互通信、数据同步的重要线程,SQL主要是实现从服务器和中继日志之间的数据传输的线程,具体的流程如下(画的不是一般的难看):
1、即server服务器开启了一个二进制日志用来记录数据的更新;
2、从服务器开启一个I/O thread 来请求同步数据,并且server 服务器也开启I/O thread 来响应从服务器,实现数据同步;
3、将从服务器用开启的I/O线程读取的数据写入到从服务器的中继日志中,之后从服务器开启SQL线程从中继日志relay-log中读取语句,逐个执行,最终实现同步数据,主从复制;
从上述流程可以看出,实现主从复制涉及到了两个日志文件,一个是主服务器的二进制日志文件,另一个是从服务器的中继日志文件,所以,如果后续工作中,主从复制的状态出现了异常,很有可能是两个日志文件的问题,具体后面再说;
对于具体的主从部署,可以大致分为以下重要步骤:
1、首先要在主服务器中支持从服务器:在/etc/my.cnf中的[ mysqld ] 中添加 log-slave-updates=true,实现开启从日志;
2、主从数据的同步需要在数据库中相互授权,才可以实现数据的同步,在主服务器中对从服务器的授权:
mysql> grant replication slave on *.* to 'mysql'@'192.168.216.%' indentified by '123123'
mysql> flush privileges;
之后再show master status 命令,会显示主服务器的二进制日志的编号和位置,记住file和position;
3、在从服务器中对主服务器授权:
mysql> change master to master_host='192.168.216.100',master_user='myslave',master_password='123123',master_log_file='mysql-bin.000002',master_log_pos=107;
mysql> start slave;
用show slave status \G 来查看线程运行是否正常,即主要看:
Slave_IO_Running:yes
Slave_SQL_Running:yes
在这里想说一点关于bin-log和relay-log 的区别:
主库的bin-log 是指主库执行过的事务记录的bin-log日志。
从库的relay-log 是指从库接收主库的bin-log日志。
从库的bin-log日志指从库通过sql线程复现relay-log后记录的日志,和从库自己执行过的事务记录的bin-log日志。
二、技术难点解决
这里主要分为两种情况,一种是I/O running =no ,另一种是SQL running =no。
当I/O运行不正常时,原因较多,可以是主服务器宕机、意外停电、或者从服务器找不到主服务器的日志文件位置,导致数据同步失败,若是外因导致,则重启即可,若是内因,可以先查看主服务器的状态:show master status \G ; 查看日志文件和位置,再对应修改和重新设置从服务器中的master_log_file和master_log_pos。在error log中,会记录在执行start slave(开始复制)后的数据复制状态,具体会记录主服务器的日志开始位置和中继日志的开始位置,还会记录开始复制的具体时间。
不过有时,排除错误不可以只看show slave status中的信息,因为有的错误信息会记录在err.log中,比如空间不足或网络中断等原因;
另外,在日志方面注意一点是从库接收的bin-log与主库执行的是否冲突,具体为:从库接收的bin-log文件的位置要大于主库执行的。
当sql运行异常时,主要看relay-log是否存在异常,有时会因为一些中继日志产生影响,我们可以设置:
在[ mysqld ]下添加:relay_log_purge=1(自动清除中继日志打开),这样从服务器的SQL 线程在每执行完一个事务之后会判断该中继日志是否还被需要,如若不被需要,则自动清除。
还有比较常见的错误是在change master时会产生1021报错,即为之前做过主从同步,需要stop slave;、reset slave;之后重新change master to ...,最后start slave;就好啦。