在实际企业应用环境当中,单台mysql数据库是不足以满足日后业务需求的。譬如服务器发生故障,没有备份服务器来提供服务的话,业务就得停止。介于这种情况,mysql经常采用主从构架,或者主主架构,这样可以实现mysql服务器的负载均衡,提升mysql服务器的性能.而关键是,可以实现mysql的数据同步复制功能,来为企业数据备份提供一种方便的机制。
MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。
默认情况下,MySQL5.5的复制功能是异步的,这意味着当谈到数据一致性时,主服务器及其从服务器是独立的。异步复制可以提供最佳的性能,因为主服务器在将更新的数据写入它的二进制日志(Binlog)文件中后,无需等待验证更新数据是否已经复制到至少一台拓扑从服务器中,就可以自由处理其它进入的事务处理请求。虽然快,但这也同时带来了很高的风险,如果在主服务器或从服务器端发生故障,会造成主服务器/从服务器数据的不一致,甚至在恢复时造成数据丢失。
因此MySQL5.5引入了一种半同步复制功能,该功能可以确保主服务器和访问链中至少一台从服务器之间的数据一致性和冗余。在这种配置结构中,一台主服务器和其许多从服务器都进行了配置,这样在复制拓扑中,至少有一台从服务器在父主服务器进行事务处理前,必须确认更新已经收到并写入了其中继日志(Relay Log)。当出现超时,源主服务器必须暂时切换到异步复制模式重新复制,直到至少有一台设置为半同步复制模式的从服务器及时收到信息。
主要注意的地方:
1) mysql复制过程在网络上传输时是明文的,不过支持SSL加密。
2) mysql复制要求主从架构的服务器的server id 不能相同。
3) 半同步复制模式必须在主服务器和从服务器端同时启用,否则主服务器默认使用异步复制模式。
使用mysql主从复制的好处有:
1) 采用主从服务器这种架构,稳定性得以提升。如果主服务器发生故障,我们可以使用从服务器来提供服务。
2) 在主从服务器上分开处理用户的请求,可以提升数据处理效率。
3) 将主服务器上的数据复制到从服务器上,保护数据免受意外的损失。
主从配置实例:
注意:如果主服务器的master事先存在,并且里面已经有数据,此时再想做主从复制,就得先将主服务器上的数据库拷贝一份到从服务器上,保证目前主从数据一致后再做主从设置。
可以使用mysqldump先从主服务器上备份一份数据,然后锁表,将数据拷贝到从服务器上,然后做主从设置,再解表!
mysqldump -uroot -p123 --all-databases --lock-all-tables > /data/mysql_bak/all_databak.sql mysqldump -uroot -p123 -R --single_transaction --master-data=2 --all-databases > /data/mysql_bak/all_databak.sql
以下是全新安装mysql主从复制(主从服务都是新装的,数据相同)
1、主从服务器分别作以下操作:
1.1、版本一致 1.2、初始化表,并在后台启动mysql 1.3、修改root的密码
2、修改主服务器master:
cat /etc/my.cnf [mysqld] log-bin=mysql-bin # [必须]启用二进制日志 server-id=200 # [必须]服务器唯一ID,默认是1,一般取IP最后一段
3、修改从服务器slave:
cat /etc/my.cnf [mysqld] log-bin=mysql-bin # [必须]启用二进制日志 server-id=201 # [必须]服务器唯一ID,默认是1,一般取IP最后一段
注意!!!master 和 slave 的server_id 不能一样
4、重启两台服务器的mysql
/etc/init.d/mysqld restart
5、在主服务器上建立帐户并授权slave:
/usr/local/mysql/bin/mysql -uroot -p123456 mysql> GRANT replication SLAVE ON *.* to 'slave'@'%' identified by '123456'; # 一般不用root帐号,“%”表示所有客户端都可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.0.250,加强安全。
6、登录主服务器的mysql,查询master的状态,并记录File和Position的值
mysql>show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000004 | 308 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) 注:执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化 mysql>flush tables with read lock; # 同时可以锁定MYSQL
7、配置从服务器Slave:
mysql>change master to master_host='192.168.0.200',master_port=3301,master_user='slave',master_password='123456',master_log_file='mysql-bin.000004',master_log_pos=308; # 注意不要断开,3301和308无单引号
mysql>unlock tables; # 主服务器解锁 mysql>start slave; # 启动从服务器复制功能
8、检查从服务器复制功能状态:
mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.200 # 主服务器地址 Master_User: redhat # 授权帐户名,尽量避免使用root Master_Port: 3306 # 数据库端口,部分版本没有此行 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 600 # 同步读取二进制日志的位置,大于等于>=Exec_Master_Log_Pos Relay_Log_File: ddte-relay-bin.000003 Relay_Log_Pos: 251 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes # 此状态必须YES Slave_SQL_Running: Yes # 此状态必须YES ...... 注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。
以上操作过程,主从服务器配置完成。
9、主从服务器测试:
主服务器Mysql,建立数据库,并在这个库中建表插入一条数据:
mysql> create database test01; Query OK, 1 row affected (0.00 sec) mysql> use test01; Database changed mysql> create table Table(id int(3),name char(10)); Query OK, 0 rows affected (0.00 sec) mysql> insert into Table values(001,'Baidu'); Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | test01 | | mysql | | test | +--------------------+ 4 rows in set (0.00 sec)
从服务器Mysql查询:
mysql>show databases; +--------------------+ | Database | +--------------------+ | information_schema | | test01 | # I'M here,大家看到了吧 | mysql | | test | +--------------------+ 4 rows in set (0.00 sec) mysql> use test01 Database changed mysql> select * from Table; # 可以看到在主服务器上新增的具体数据 +------+------+ | id | name | +------+------+ | 1 | Baidu | +------+------+ 1 row in set (0.00 sec)
10、监控从的状态:
编写一shell脚本,用nagios监控slave的两个“yes”,如发现只有一个或零个“yes”,就表明主从有问题了,发短信警报吧。
mysql -h127.0.0.1 -P3306 -uroot -p123456 -e "show slave status\G" | grep -Ec "(Slave_IO_Running: Yes|Slave_SQL_Running: Yes)" | awk '{if($1 == 2){print "OK mysql-slave";exit(0);}else{print "Critical mysql-slave";exit(2)}}' # 简单命令
以下是2个脚本
1)cat mysql_state1.sh
#!/bin/bash
DB_PW=123456
port="3301 3302 3303"
for i in $port;do
mysql -h127.0.0.1 -P$i -uroot -p${DB_PW} -e "show slave status\G" |
grep -Ec "(Slave_IO_Running: Yes|Slave_SQL_Running: Yes)" |
awk '{if($1 == 2){print "OK mysql-slave";exit(0);}else{print "Critical mysql-slave";exit(2)}}'
done
2)cat mysql_state2.sh
#!/bin/bash
DB_PW=admin
Ports="3301 3302 3303"
Mysql_ip=`ifconfig | awk -F'[ :]+' 'NR==2{print $4}'`
for port in ${Ports}; do
Num=`mysql -h127.0.0.1 -P${port} -uroot -p${DB_PW} -e "show slave status\G" | grep -Ec "(Slave_IO_Running: Yes|Slave_SQL_Running: Yes)"`
Mysql_port=`netstat -tnlp |grep ${port} | awk -F'[: ]+' '{print $5}'`
if [ ${Mysql_port} == ${port} ]; then
echo "${Mysql_ip}_${port} Mysql is running"
else
echo "Mysql is not running" | mail -s "Warning!Server: ${Mysql_ip}_${port} mysql is down" [email protected]
echo "Waining! ${Mysql_ip}_${port} mysql is down"
fi
if [ $Num == 2 ]; then
echo "${Mysql_ip}_${port} Slave is running"
else
echo "Slave is not running!" | mail -s "Warning! ${Mysql_ip}_$port Slave is not running" [email protected]
echo "Warning! ${Mysql_ip}_${port} Slave is not running"
fi
done
错误分析:
1)Slave_SQL_Running: No
原因:
1.程序可能在slave上进行了写操作
2.也可能是slave机器重起后,事务回滚造成的.
解决办法I:
1.首先停掉Slave服务:slave stop;
2.到主服务器上查看主机状态:show master status\G 记录File和Position对应的值。
3.到slave服务器上执行手动同步:
change master to master_host='192.168.0.200',master_port=3301,master_user='redhat',master_password='123456',master_log_file='mysql-bin.000004',master_log_pos=308;
4.start slave;
解决方法二:
1.stop slave;
2.set global sql_slave_skip_counter=1;
3.start slave;
转载于:https://blog.51cto.com/liumissyou/957344