前段时间写过一篇文章 《企业级数据备份,rsync加shell编程,实现增量备份 》,这篇文章的备份原理是每天将数据库导出来,打包,传送到备份服务器上去,在长时间使用的时候,发现了一些缺点,由于数据库数据每日增加,每次在导出的时候,mysqldump及tar打包,占用系统资源过多且耗时过长,导到持续CPU爆高,并且在传输数据文件的时候,虽然做了限速,但是还是影响网站打开速度。所以不得不优化备份程序及策略了。
   我的备份服务器配置还不错的,只作存储使用挺浪费的,所以想,为什么不用mysql主从复制把数据同步到备份服务器上,然后在备份服务器上,导出,打包,如果这种构思成功的话,就能将导出数据及打包这种非常消耗资源动作转移到备份服务器上。且大大减少了传输时的占用带宽比,经过了解,mysql主从复制,基本上是不占用带宽的。
  经过一上午的实验,发现这种构思是成功的,并且成功的运用了生产环境。下面我就将生产环境中的一些配置及写的一些检查脚本简要说明一下。 
一,服务器环境:
  1. 生产服务器: A:192.168.1.10  : mysql版本 5.1.34 
  2. 生产服务器: B:192.168.1.11  : mysql版本 5.1.34 
  3. 备份服务器: C:192.168.1.20  : mysql版本 5.1.34 
二,配置mysql主从同步
1,生产服务器A配置:
开启A服务器mysqlbinlog,设置id号并重新启动:
  1. vim /etc/my.cnf  
  2. log-bin = binlog  
  3. server-id = 1  
  4.  
  5. #service mysql restart 
2:设置备份服务器C同步A服务器my的用户名密码
    创建帐号:(A  服务器上操作)
  1. mysql>GRANT super,REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123456'; 
  2. mysql>flush privileges; 
  3.  
  4. (注:slave 及 123456分别为用户名密码) 
3,将A服务器数据库数据导出,传输到C服务器上,并导入C服务器数据库
4,配置C服务器的my.cnf 加入以下参数.并启动C服务器上的数据库
 
  1. vim /etc/my.cnf 
  2. server-id       = 2  #此处id应与主服务器id不同
  3. master-host=192.168.1.10 
  4. master-user=slave 
  5. master-password='123456' 
  6. master-port=3306 
  7. relay-log=relay-bin 
  8. relay-log-index=relay-bin 
  9.   
  10. #service mysql start 
5,查看A服务器日志及偏移量
  1. mysql>show master status\G  输出如下图

优化企业级备份策略,实现无负载数据库备份及监控_mysql主从复制

这里面显示日志文件为 binlog.00629,偏移量为 1495278  (每台服务器都不一样,以自己服务器为准)
6,在备份服务器C上的mysql服务里面运行以下命令,同步两台服务器
  1. mysql>stop slave; 
  2. mysql>reset slave; 
  3. mysql>change master to master_host='192.168.1.10'master_user='slave',master_password='123456',master_log_file=’binlog.00629',master_log_pos=1495278
  4. mysql>slave start; 
启动mysql slave
查看是否正常运行
  1. mysql>show slave status\G 

优化企业级备份策略,实现无负载数据库备份及监控_备份_02

如果
  1. Slave_IO_Running: Yes 
  2. Slave_SQL_Running: Yes 
那说明slave 是正常运行的
执行这些程序后,从服务器应连接主服务器,并同步生产服务器A上面的任何更新。
三,启动一个新的mysql 服务, 这里简述为mysql2,作为生产服务器B的slave
1,拷贝my.cnf 作为mysql2配置文件,并作相应修改 
 
  1. #cp /etc/my.cnf  /etc/my2.cnf 
  2.  
  3. vim /etc/my2.cnf 
  4. [client] 
  5. port    = 3307 
  6. socket  = /tmp/mysql2.sock 
  7.  
  8. [mysqld] 
  9. user    = mysql 
  10. port    = 3307 
  11. socket  = /tmp/mysql2.sock 
  12.  
  13. server-id       = 3  #此处id应与主服务器id不同 
  14. master-host=192.168.1.11 
  15. master-user=slave 
  16. master-password='123456'
  17. master-port=3306 
  18. relay-log=relay-bin 
  19. relay-log-index=relay-bin 
2,先初始化一下数据库
  1. /usr/local/webserver/mysql/bin/mysql_install_db  --datadir=/home/mysql/var2 --user=mysql 
3,启动mysql2服务器
 
  1. /usr/local/webserver/mysql2/bin/mysqld_safe --defaults-file=/etc/my2.cnf --basedir=/usr/local/webserver/mysql --datadir=/home/mysql/var2 --user=mysql&  
  2.  
  3. 参数简介  
  4. --defaults-file=/etc/my2.cnf              #指定配置文件路径   
  5. --basedir=/usr/local/webserver/mysql      #指定程序文件路径   
  6. --datadir=/home/mysql/var2                #指定数据文件路径   
  7. --user=mysql&                             #指定启动用户   
这样。我们又启动了一个新的mysql进程。
  1. 进入mysql2方式为          mysql --socket=/tmp/mysql2.sock –p密码 
  2. 导入数据至mysql2方式为:  mysqldump --socket=/tmp/mysql2.sock  -p密码 
按照上面的步骤,把 B 服务器的数据导入到C服务器的mysql2下,并启动slave.
注意:如果生产服务器里的表有innodb格式的,这样的方法不行,必须重新编译一个mysql服务器启动,
四:编写脚本备份C服务器中的数据
1,编写脚本
  1. #vim /home/alldbbak/dbbak.sh 
  2.  
  3. #! /bin/bash 
  4. for db in `ls /home/mysql/var/` 
  5. do 
  6. if [ -d /home/mysql/var/$db ];then 
  7. mysqldump  $db  >/home/alldbbak/dbcache/$db.sql 
  8. fi 
  9. done 
  10. cd /home/alldbbak/dbcache/ 
  11. tar -cvzf 192.168.1.10.`date +"%Y%m%d"`.tar * 
  12. find /home/alldbbak/ -name "*.tar" -mtime +5 -exec rm -rf {} \; 
  13. mv *.tar .. 
  14. rm -rf /home/alldbbak/dbcache/*.sql 
  15. cd /home/alldbbak/ 
  16.  
  17. for db in `ls /home/mysql/var2/` 
  18. do 
  19. if [ -d /home/mysql/var2/$db ];then 
  20. mysqldump --socket=/tmp/mysql2.sock $db >/home/alldbbak/dbcache/$db.sql 
  21. fi 
  22. done 
  23. cd /home/alldbbak/dbcache/ 
  24. tar -cvzf 192.168.1.11.`date +"%Y%m%d"`.tar * 
  25. find /home/alldbbak/  -name "*.tar" -mtime +5 -exec rm -rf {} \; 
  26. mv *.tar .. 
  27. rm -rf /home/alldbbak/dbcache/*.sql 
  28. cd /home/alldbbak/ 
  29. done 
脚本这块解释请参照《企业级数据备份,rsync加shell编程,实现增量备份
2, 定时运行
  1. #crontab –e 
  2. 00 07 * * * sh /home/alldbbak/dbbak.sh #每天早上7点运行
五:编写脚本检查slave服务器状态,并在slave同步同出错后重新同步
1, 先写好sock文件与ip对应关系
  1. #vim /home/alldbbak/duiyin 
  2. /tmp/mysql.sock    192.168.1.10 
  3. /tmp/mysql2.sock   192.168.1.11  
2, 编写检查脚本
  1. #vim /home/alldbbak/autocheck.sh
  2. #! /bin/bash 
  3. for i in `seq 1 2` 
  4. do 
  5. server=`sed -n "$i"p /home/alldbbak/duiyin|awk '{print $2}'` 
  6. socket=`sed -n "$i"p /home/alldbbak/duiyin|awk '{print $1}'` 
  7. for m in `mysql --socket=$socket  -e "show slave status\G"|grep Running|awk '{print $2}'|sed 'N;s/\n//g'` 
  8. do 
  9. if [ $m != "YesYes" ];then 
  10. pos=(`mysql -h$server –p密码 -e "show master status\G"|sed -n '2,3'p|awk '{print $2}'|sed 'N;s/\n/ /g'`) 
  11. mysql --socket=$socket  <<EOF 
  12. slave stop; 
  13. reset slave; 
  14. change master to master_host="$server"master_user='slave',master_password='123456',master_log_file="${pos[0]}",master_log_pos=${pos[1]}; 
  15. slave start; 
  16. EOF 
  17. sleep 2 
  18. yes=`mysql --socket=$socket  -p密码 -e "show slave status\G"|grep Running|awk '{print $2}'|sed 'N;s/\n//g'` 
  19. if [ $yes == "YesYes" ];then 
  20. fetion --mobile=飞信帐号 --pwd=飞信密码 --to=监控手机号码 --msg-utf8="$server  同步成功" 
  21. else 
  22. fetion --mobile=飞信帐号 --pwd=飞信密码 --to=监控手机号码  --msg-utf8="$server 同步失败" 
  23. fi 
  24. fi 
  25. done 
  26. done 
脚本解释
  1. #! /bin/bash 
  2. for i in `seq 1 2` 
  3. do 
  4. server=`sed -n "$i"p /home/alldbbak/duiyin|awk '{print $2}'`    #分别赋值服务器ip
  5. socket=`sed -n "$i"p /home/alldbbak/duiyin|awk '{print $1}'`     #分别赋值sock文件
  6. for m in `mysql --socket=$socket  -e "show slave status\G"|grep Running|awk '{print $2}'|sed 'N;s/\n//g'`   
  7.  
  8. #分别判断两个库的Slave_IO_Running:与 Slave_SQL_Running 是否等于YesYes 这里我把两个Yes合并在一起了 
  9.  
  10. do 
  11. if [ $m != "YesYes" ];then 
  12. pos=(`mysql -h$server –p密码 -e "show master status\G"|sed -n '2,3'p|awk '{print $2}'|sed 'N;s/\n/ /g'`)   
  13.  
  14. #如果两个值不等于Yes,就重新获取主服务器上的值。赋值给了pos变量,这里用了一个数组
  15.  
  16. mysql --socket=$socket  <<EOF 
  17. slave stop; 
  18. reset slave; 
  19. change master to master_host="$server"master_user='slave',master_password='123456',master_log_file="${pos[0]}",master_log_pos=${pos[1]};    #重新同步一下slave库,并启动 
  20. slave start; 
  21. EOF 
  22.  
  23. # 进入mysql 运行命令,重新同步数据。
  24.  
  25. sleep 2 
  26. yes=`mysql --socket=$socket  -p密码 -e "show slave status\G"|grep Running|awk '{print $2}'|sed 'N;s/\n//g'` 
  27.  
  28. #2秒后重新判断两个库的Slave_IO_Running:与 Slave_SQL_Running 是否等于YesYes
  29.  
  30. if [ $yes == "YesYes" ];then    
  31. fetion --mobile=飞信帐号 --pwd=飞信密码 --to=监控手机号码 --msg-utf8="$server 同步成功" 
  32. else 
  33. fetion --mobile=飞信帐号 --pwd=飞信密码 --to=监控手机号码 --msg-utf8="$server 同步失败" 
  34. fi 
  35. fi 
  36. done 
  37. done 
  38. #最后用飞信软件,发送一下恢复结果给监控手机。飞信安装可以在网上查一下资料。
     
2, 加入计划任务
  1. */5 * * * * sh /home/alldbbak/autocheck.sh   #每5会钟执行一次
这样的话,就可以添加一个同步监控了,出错了,他能自动的去修复,如果修复不了只能手动去修复一下了 
  这样改变一下备份的策略,非常好的优化了服务器在备份时的负载,生产服务器备份时只要增量的传输一些新生成的文件即可。
  有什么不明白的,可以加我QQ相互讨论:410018348
 
最后推广一下我的网站  看电影网