MySQL主从复制原理及配置详细过程以及主从复制集群自动化部署的实现
一、复制概述
Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。
二、MySQL支持复制的类型也就是二进制日志格式:
- 基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高
- 基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
- 混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。
三、复制的特点:
- 数据分布
- 负载均衡
- 备份
- 高可用性和可用行
四、复制进程的实现:
Mysql的复制(replication)是一个异步或半同步的复制,从一个Mysql 实例(称之为Master)复制到另一个Mysql 实例(称之Slave)。实现整个复制操作主要由三个进程完成的,其中两个进程在Slave(Sql进程和IO进程),另外一个进程在 Master(IO进程)上。
要实施复制,首先必须打开Master端的binary log(bin-log)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。
具体过程如下:
- Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
- Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
- Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
- Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
五、配置过程:
MySQL主从复制配置:
环境:
master.test.com-->172.16.3.201
slave.test.com-->172.16.3.203
master.test.com-->172.16.3.201
1、启用二进制日志
vim /etc/mysql/my.cnf
# 确保[mysqld]中有如下语句
log-bin=mysql-bin# 保存退出
2、设置一个在当前集群中唯一的server-id
vim /etc/mysql/mys.cnf
# 定位至如下行
server-id = 1
# 把其值设置为11,也可以设置其他
server-id = 11
# 保存退出
上述过程用sed实现:
sed -i '/^server-id/s@1@11@' /etc/mysql/my.cnf
3、创建一个有复制权限的账号包括[replication slave,replication client]:
mysql -e "grant replication client,replication slave on *.* to 'repluser'@'172.16.3.203' identified by 'replpass'; flush privileges;"
4、service mysqld restart
slave.test.com-->172.16.3.203
1、启用中继日志
vim /etc/mysql/my.cnf
# 在里面的mysqld段中加入如下内容:开启中继日志
relay-log = relay-bin
# 保存退出
用sed实现:
sed -i '/\[mysqld\]/a relay-log = relay-bin' /etc/mysql/my.cnf
2、设置一个在当前集群中唯一的server-id
vim /etc/mysql/my.cnf
# 定位至如下行
server-id =1
# 把其值设置为其21,也可以设置为其他
server-id =21
# 保存退出
# 用sed实现
sed -i '/^server-id/s@1@21@' /etc/mysql/my.cnf
3、设置MySQL只读
用sed实现:
sed -i '/\[mysqld\]/a read-only = on' /etc/mysql/my.cnf
4、service mysqld restart
5、使用有复制权限账号连接至主服务器
mysql -e "change master to master_host='172.16.3.201', master_user='repluser', master_password='replpass', master_log_file='binlog.000033', master_log_pos=553, master_connect_retry=5, master_heartbeat_period=2"
6、启动从服务器
mysql -e "start slave"
可能遇到的报错:
ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MariaDB error log
解决方法:
该报错如果出现,就会出现在slave中,处理方法如下:
MariaDB [(none)]> reset slave;
MariaDB [(none)]> change master to master_host='172.16.3.201', master_user='repluser', master_password='replpass', master_log_file='binlog.000033', master_log_pos=245, master_connect_retry=5, master_heartbeat_period=2;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.3.201
Master_User: repluser
Master_Port: 3306
Connect_Retry: 5
Master_Log_File: binlog.000033
Read_Master_Log_Pos: 245
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 526
Relay_Master_Log_File: binlog.000033
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
自动化部署MySQL主从复制集群【脚本实现】:
说明:通过shell脚本实现自动化部署MySQL主从复制集群,这里我就不解释每一步的意义了,在前面的介绍,有每一步骤的详细解释,我这个脚本仅供大家参考,经过了我的亲测,可以自动化部署,如有哪里不足还请大家多多给些意见,我也是新手,大家一起学习,嘿嘿
master_slave.sh
#!/bin/bash if [[ $# -eq 0 ]]; then echo "Usage: /bin/bash `basename $0` master_ip slave_ip" exit 1 fi master_ip=$1 slave_ip=$2 sed -i '/^server-id/s@1@11@' /etc/mysql/my.cnf mysql -e "grant replication client,replication slave on *.* to 'repluser'@"${slave_ip}" identified by 'replpass'; flush privileges;" service mysqld restart cat > test_master_slave.sh << EOF #!/bin/bash sed -i '/\[mysqld\]/a relay-log = relay-bin' /etc/mysql/my.cnf sed -i '/^server-id/s@1@21@' /etc/mysql/my.cnf sed -i '/\[mysqld\]/a read-only = on' /etc/mysql/my.cnf service mysqld restart mysql -e "change master to master_host='172.16.3.101', master_user='repluser', master_password='replpass', master_log_file='binlog', master_log_pos=55, master_connect_retry=5, master_heartbeat_period=2" mysql -e "start slave" EOF master_log=`mysql -e "show master status" | grep 'bin' | awk '{print $1}'` master_log_position=`mysql -e "show master status" | grep 'bin' | awk '{print $2}'` sed -i "/binlog/s@binlog@${master_log}@" test_master_slave.sh sed -i "/log_pos/s@55@${master_log_position}@" test_master_slave.sh sed -i "/master_host/s@172.16.3.101@${master_ip}@" test_master_slave.sh echo ${master_log} echo ${master_log_position} scp test_master_slave.sh node2:/root ssh node2 "/bin/bash /root/test_master_slave.sh"
该脚本用到了shell的基本知识,还有sed、awk等的很基础的知识;