MySQL 5.5 主从复制

 

MySQL 5.5 主从复制的原理、过程
 
分为同步复制和异步复制,实际复制架构中大部分为异步复制。复制的基本过程以下: 
1)、Slave上面的IO进程链接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)以后的日志内容;  

2)、Master接收到来自Slave的IO进程的请求后,经过负责复制的IO进程根据请求信息读取指定日志指定位置以后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息以外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的pos位置;  

3)、Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的中继日志(relay-log)文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master.info文件中,以便在下一次读取的时候可以清楚的告诉Master“我须要从某个bin-log的哪一个pos位置开始日后的日志内容,请发给我”;

4)、Slave的sql进程检测到relay-log中新增长了内容后,会立刻解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。   

Slave端的双进程复制提高可靠性
Mysql为了解决这个风险并提升复制的性能,将Slave端的复制改成两个进程来完成。提出这个改进方案的人是Yahoo!的一位工程师“Jeremy Zawodny”。这样既解决了性能问题,又缩短了异步的延时时间,同时也减小了可能存在的数据丢失量。固然,即便是换成了如今这样两个线程处理之后,一样也仍是存在Slave数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事物中,这些问题都是会存在的。若是要彻底避免这些问题,就只能用mysql的cluster来解决了。不过mysql的cluster是内存数据库的解决方案,须要将全部数据都load到内存中,这样就对内存的要求就很是大了,对于通常的应用来讲可实施性不是太大。

经常使用主从复制架构 
Mysql复制环境90%以上都是一个Master带一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。由于只要master和slave的压力不是太大(尤为是slave端压力)的话,异步复制的延时通常都不多不多。尤为是自slave端的复制方式改为两个进程处理以后,更是减少了slave端的延时。而带来的效益是,对于数据实时性要求不是特别的敏感度的应用,只须要经过廉价的pc server来扩展slave的数量,将读压力分散到多台slave的机器上面,便可解决数据库端的读压力瓶颈。这在很大程度上解决了目前不少中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用相似方案解决数据库瓶颈。


1、准备实验环境:
    主(Master)机IP: 192.168.137.26
    从(Slave) 机IP: 192.168.137.27
    两MySQL服务器均是源码包编译安装

2、向主(Master)机添加远程登陆的受权用户
    1.向主(Master)服务器添加用户:
      @ 用户名: slave4
      @ 密  码: 789
      @ 容许自: 192.168.137.27 机器登陆

      受权方式1: 此种受权是可远程登陆Master,仅用于主从复制没有其它任何select insert update等权限【推荐】
      mysql> grant replication slave on *.* to 'slave4'@'192.168.137.27' identified by '789';

      受权方式2: 此种受权是对用户不但可远程登陆Master,还可拥有对Master包括主从复制的其它全部select insert update等权限
      mysql> grant all on *.* to 'slave6'@'192.168.137.28' identified by '789';

    2.刷新受权表:
      mysql> flush privileges;

    3.查看受权结果:
      mysql> show grants for 'slave4'@'192.168.137.27';

    4.测试从Slave端登陆远程主(Master)机:
      # /usr/local/mysql/bin/mysql -uslave4 -p789 -h192.168.137.26

    5.从主(Master)机查看全部链接登陆本机的客户端状况:
      mysql> show processlist \G


3、主(Master)机配置
    vi编辑打开mysql配置文件
    # vi /usr/local/mysql/etc/my.cnf

    找到从约第56行开始确认如下三项:
    [mysqld]
    log-bin=mysql-bin    # 确认开启binlog日志
    binlog_format=mixed  # 确认binlog日志格式为mixd混合类型
    server-id = 1        # 在整个主从架构内指定一个惟一的server-id,范围:1^32


4、从(Slave)机配置-【基本】
    vi编辑打开mysql配置文件
    # vi /usr/local/mysql/etc/my.cnf

    找到从约第56行开始确认如下三项: 
    [mysqld]
    log-bin=mysql-bin    # 确认也开启binlog日志
    binlog_format=mixed  # 确认binlog日志格式为mixd混合类型
    server-id = 2        # 在整个主从架构内指定一个惟一的server-id,范围:1^32 ◆


    从(Slave)机配置-【可选】
    下面是生产阶段可能要用的功能,这些功能只能在从机的配置文件的[mysqld]区块里手工配置,没法经过 change master to ...命令实现。
    1.白名单 - 只想复制某(些)个库:
      replicate_do_db=zyyshop                 # 追加复制zyyshop库
      replicate_do_db=test                    # 追加只复制test库
      总结: 至关于只复制 zyyshop、test 两个库
            若是采用彻底在配置文件里配置主(Master)机信息的方法,此项须添加,不然可能致使mysqld启动不了 

    2.白名单 - 只想复制某(些)个库(的全部表)
      replicate_wild_do_table=zyyshop.%       # 追加复制zyyshop库的全部表
      replicate_wild_do_table=test.%          # 追加复制test库的全部表
      总结:也是至关于只复制 zyyshop、test 两个库。

    3.白名单 - 只想复制某(些)个库(的部分表)
      replicate_wild_do_table=zyyshop.stu     # 追加zyyshop.stu表
      replicate_wild_do_table=test.project    # 追加test.project表
      总结:至关于只复制zyyshop.stu、test.project两个表。

    4.黑名单 - 想忽略对mysql和test数据库的复制
      replicate_ignore_db=mysql               # 追加mysql库为忽略
      replicate_ignore_db=test                # 追加test库为忽略
      总结:至关于将mysql和test两数据库追加到忽略列表,将不会被复制。
    
    5.黑名单 - 想忽略对某些库的某些表的复制
      replicate_wild_ignore_table=mysql.users # 追加mysql.users表为忽略
      总结:本步骤是至关于追加了mysql.users具体的表被忽略,其它表照常会被复制。
      
    6.若是想实现“主-->从-->从”的链式架构,由于在默认状况下,from主(Master)机copy过来的数据不会写入从(Slave)机的binlog日志里,
      而是写入中继日志(localhost-relay-bin.00000x)里,因此本机若是还须要充当其它机器的主机,就将从主机复制来的数据写入从库时同
      时也显式地写入本地binlog日志,添加以下配置:
      log-slave-updates =1

5、在主(Master)机端操做:执行命令刷新主机binlog日志记录,查看主机的最后日志文件及最后pos起始点
    mysql> flush logs;
    mysql> show master status;
    +------------------+----------+--------------+------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000009 |      107 |              |                  |
    +------------------+----------+--------------+------------------+

6、在从(Slave)机启动slave服务
    1.使用root用户登陆到从(Slave)机
      # /usr/local/mysql/bin/mysql -uroot -p123456

    2.在从(Slave)上执行命令,动态改变链接到主(Master)机的配置,生成或更新master.info文件:
      注: 在生产环境中,若是心跳感应到主机意外宕机,应用程序应该按预案选定出一台新主机,而其它的从机都须要执行一次下面
          的 change master to ...语句,切换本身从属到新主机,这样比较灵活,操做的实质是更新master.info文件,查看此文件也
          能发现MySQL实际上是只能支持“一主多从”架构,而不能像Redis那样还能够支持多主一从架构。

      mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='mysql-bin.000009', MASTER_LOG_POS=107;

      善于使用?查看详细选项
      mysql> ? change master to

      经常使用选项:
       master_host='192.168.137.26' 远程主(Master)机IP      
       master_user='slave4',        登陆远程主(Master)机 用户名
       master_password='789',       登陆远程主(Master)机 密码

      不经常使用选项:      
       MASTER_LOG_FILE='mysql-bin.000009' 指定从哪一个binlog文件复制(若是不加此参数默认是最先的binlog日志)
       MASTER_LOG_POS=107                 指定从哪一个binlog文件的哪一个pos点开始复制(若是不加此参数默认是最先的pos点)
       MASTER_PORT=3306,                  远程主(Master)机端口
       MASTER_HEARTBEAT_PERIOD=60         多长时间探测一次主服务器是否在线 单位:秒
       MASTER_CONNECT_RETRY=10;           没法链接主服务器的时候重试链接的间隔时间 单位:秒


    3.启动IO线程和SQL线程,生成master.info文件,查看从(Slave)机状态:
      mysql> start slave;
      mysql> show slave status \G;

      若是看到以下状态说明同步成功:             
           Slave_IO_Running: Yes
          Slave_SQL_Running: Yes
      Seconds_Behind_Master: 0


    4.报错处理!若是“Slave_SQL_Running: No”,程序可能在slave上进行了写操做,也多是slave机器重起后,事务回滚形成的。
      解决方法一: 
      mysql> stop slave;
      mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
      mysql> start slave;
      mysql> show slave status \G;

      解决方法二:
      主(Master)上:
      mysql> show master status;  //主机上查看最新的binlog日志名及pos点

      从(Slave)机上:
      mysql> stop slave;          //从机停掉slave服务
      mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='主机最新binlog日志名', MASTER_LOG_POS=最新pos点;
      mysql> start slave;
      mysql> show slave status \G;
      


7、【实验】若是开始的环境不是主从架构,跑了一段时间主(Master)机已经有了数据,且主机的binlog日志已经不完整了,可由两种方案:

    方案一(推荐):对主(Master)机作一次完整的mysqldump备份,拷贝到从(Slave)机执行从机恢复,而后从机再开启slave服务

      A.【主机操做】备份主机数据(好比:test和zyyshop是须要之后同步的库)
         # /usr/local/mysql/bin/mysqldump -uroot -p123456 -lF --log-error=/root/myDump.err -B test zyyshop > /root/test_zyyshop.sql

      B.【主机操做】当即查看一下主机的最新的binlog日志,并记录binlog日志名和pos点,从机就从这儿开始同步便可:
         # /usr/local/mysql/bin/mysql -uroot -p123456
         mysql> show master status;
         +------------------+----------+--------------+------------------+
         | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
         +------------------+----------+--------------+------------------+
         | mysql-bin.000012 |      107 |              |                  |
         +------------------+----------+--------------+------------------+

      C.【主机操做】将备份的文件直接恢复到远程的从(Slave)机数据库上:     
         方法1:先将 test_zyyshop.sql 备份文件 SCP 拷贝到远程从(Slave)机,再登陆到远程从机恢复:
                A.拷贝备份数据到从机:
                  # scp /root/test_zyyshop.sql root@192.168.137.27:/root/masterdb.sql
                  须要两台机器都安装scp才可,scp属于openssh-clients这个包,安装方法:# yum install -y openssh-clients

                B.[从机操做]将从机的备份数据恢复:
                  # /usr/local/mysql/bin/mysql -uroot -p123456 -v < /root/masterdb.sql

         方法2:直接恢复到远程从(Slave)机上:
                # /usr/local/mysql/bin/mysql -uroot -p123456 -h192.168.137.27 -v < /root/test_zyyshop.sql

         至此从机已将主机的备份文件恢复到从机,接下来只要不断向主机同步binlog日志就OK了。

      D.[从机操做] 在从(Slave)上执行命令,动态改变链接到主(Master)机的配置,生成或更新master.info文件:
        # /usr/local/mysql/bin/mysql -uroot -p123456        

        mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=107;  

        mysql> start slave;
        mysql> show slave status \G;

        *************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.137.26
                  Master_User: slave4
                  Master_Port: 3306
                Connect_Retry: 10
              Master_Log_File: mysql-bin.000012
          Read_Master_Log_Pos: 107
               Relay_Log_File: zzx-relay-bin.000002
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000012
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

        ................

    小结:若是slave启动一切正常,就成功了!



    方案二:打包主机的数据目录拷贝到从(Slave)机进行从机恢复,而后从机再开启slave服务
            ★ 注: 此法适用于MyISAM引擎表,不适用于Innodb引擎表。

      # /usr/local/mysql/bin/mysql -uroot -p123456

      A.【主机操做】对主(Master)机全部表进行“读锁”:     
         mysql> flush tables with read lock;

         查看一下主机的最新的binlog日志,并记录binlog日志名和pos点,从机就从这儿开始同步便可:
         mysql> show master status;
         +------------------+----------+--------------+------------------+
         | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
         +------------------+----------+--------------+------------------+
         | mysql-bin.000012 |      107 |              |                  |
         +------------------+----------+--------------+------------------+

      B.【主机操做】进入数据目录,打包须要的数据库包
        # cd /usr/local/mysql/data/
        # tar -zcvf  test.tar.gz test
        # tar -zcvf zyyshop.tar.gz zyyshop

      C.【主机操做】打包完成对主(Master)机全部表“解锁”:
        mysql> unlock tables;

      D.【主机操做】将两数据库打包文件SCP到从(Slave)机的数据目录中:
        # scp test.tar.gz zyyshop.tar.gz root@192.168.137.27:/usr/local/mysql/data/

      E.[从机操做]进入数据存放目录,解压数据包(生成数据库):
        # cd /usr/local/mysql/data/ 
        # tar -zxvf test.tar.gz
        # tar -zxvf zyyshop.tar.gz

      F.[从机操做] 在从(Slave)上执行命令(改变)链接主(Master)机,生成或更新master.info文件:
        此步同上D步,略......
      
   
      
8、主从复制中的几个重要文件
    IO线程只负责从主(Master)机端复制 mysql-bin.00000x 日志,并把复制来的数据所有都放到 localhost-relay-bin.00000n 日志里。
    SQL线程读取中继日志(relay-log.info)里的信息,将 localhost-relay-bin.00000n 日志里的数据写入本地从(Slave)机。

    1.master.info 做用:
      A.记录链接到主(Master)机的帐号和密码;
      B.记录复制到主(Master)机的哪一个二进制文件和复制到二进制文件的位置(pos点);

    2.relay-log.info 中继日志,做用:
      A.记录了写了多少数据到本地从(Slave)机中;

      
附、show slave status\G 返回信息解析:
    *************************** 1. row ***************************  
                   Slave_IO_State: Waiting for master to send event   # IO的线程的状态  
                      Master_Host: 192.168.137.26                     # 连接主服务器的IP  
                      Master_User: mark                               # 登陆主服务器用户名  
                      Master_Port: 3306                               # 登陆主服务器端口  
                    Connect_Retry: 10                                 # 主从断开后,多少秒从新连接  
                  Master_Log_File: mysql-bin.000004                   # 从服务器I/O 线程当前读取的主服务器二进制日志文件的名字  
              Read_Master_Log_Pos: 190                                # 从服务器I/O 线程从当前的主服务器二进制日志中读取的位置起点。  
                   Relay_Log_File: ip_lb-relay-bin.000002             # 从服务器SQL 线程当前读取并执行的中继日志文件的名字  
                    Relay_Log_Pos: 336                                # 从服务器SQL 线程当前从中继日志中读取执行的位置起点。  
            Relay_Master_Log_File: mysql-bin.000004                   # 从服务器中的SQL进程中正在执行的语句的位置  
                 Slave_IO_Running: Yes     # 从服务器的IO线程运行是否开启  
                Slave_SQL_Running: Yes     # 从服务器的SQL线程运行是否开启  
                  Replicate_Do_DB:         # 主从须要复制的数据库名  
              Replicate_Ignore_DB:         # 主从不须要复制的数据库名  
               Replicate_Do_Table:         # 主从须要复制的表           
           Replicate_Ignore_Table:         # 主从不须要复制的表  
          Replicate_Wild_Do_Table:         # 能够跨库复制的表  
      Replicate_Wild_Ignore_Table:         # 不能跨库复制的表  
                       Last_Errno: 0       # 最后复制的错误号...0表示没有错误  
                       Last_Error:         # 最后复制的错误信息  
                     Skip_Counter: 0       # 最近被使用的用于SQL_SLAVE_SKIP_COUNTER的值。(这个值表示跳过多少个事件在来执行SQL)  
              Exec_Master_Log_Pos: 190     # SQL线程执行到主服务器log-bin文件的位置.若是这个值与Read_Master_Log_Pos同样.则能够证实    
                  Relay_Log_Space: 492     # 全部原有的中继日志结合起来的总大小。  
                  Until_Condition: None    # 在START SLAVE语句的UNTIL子句中指定的值  
                   Until_Log_File:         # 在START SLAVE语句的UNTIL子句中指定的值  
                    Until_Log_Pos: 0       # 在START SLAVE语句的UNTIL子句中指定的值  
               Master_SSL_Allowed: No      # 这些字段显示了被从属服务器使用的参数。这些参数用于链接主服务器。  
               Master_SSL_CA_File:   
               Master_SSL_CA_Path:   
                  Master_SSL_Cert:   
                Master_SSL_Cipher:   
                   Master_SSL_Key:   
            Seconds_Behind_Master: 0   # 本字段是从属服务器“落后”多少的一个指示。当从属SQL线程正在运行时(处理更新),  
                                         本字段为在主服务器上由此线程执行的最近的一个事件的时间标记开始,已通过的秒数。  
                                         当此线程被从属服务器I/O线程遇上,并进入闲置状态,等待来自I/O线程的更多的事件时,本字段为零。  
                                         总之,本字段测量从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。  
                                         若是主服务器和从属服务器之间的网络链接较快,则从属服务器I/O线程会很是接近主服务器,  
                                         因此本字段可以十分近似地指示,从属服务器SQL线程比主服务器落后多少。  
                                         若是网络较慢,则这种指示不许确;从属SQL线程常常会遇上读取速度较慢地从属服务器I/O线程,  
                                         所以,Seconds_Behind_Master常常显示值为0。即便I/O线程落后于主服务器时,也是如此。  
                                         换句话说,本列只对速度快的网络有用。  
                                         即便主机和从机不具备相同的时钟,时间差计算也会起做用(当从属服务器I/O线程启动时,计算
                                         时间差。并假定今后时之后,时间差保持不变)。  
                                         若是从属SQL线程不运行,或者若是从属服务器I/O线程不运行或未与主服务器链接,  
                                         则Seconds_Behind_Master为NULL(意义为“未知”)。  
                                         举例说明,若是在从新链接以前,从属服务器I/O线程休眠了master-connect-retry秒,则显示NULL,  
                                         由于从属服务器不知道主服务器正在作什么,也不能有把握地说落后多少。  
    Master_SSL_Verify_Server_Cert: No  
                    Last_IO_Errno: 0  
                    Last_IO_Error:   
                   Last_SQL_Errno: 0  
                   Last_SQL_Error:   
      Replicate_Ignore_Server_Ids:   
                 Master_Server_Id: 1  
    1 row in set (0.00 sec)  



参考文档:

MySQL5.5 主从复制 
http://blog.csdn.net/m582445672/article/details/7731565

mysql5.5 主从复制 (触发器,函数,存储引擎,事件处理)说明 
http://blog.csdn.net/m582445672/article/details/7670802

Mysql主从复制[生产环境]
http://wenku.baidu.com/link?url=a-SLn41EKYseSxikYViSqvf9IBwGh7d0NsaKPnBbZjc3sED4VF_NfpjMT5IrUhC3yeuq75geJuglzrz2RXmY41t3mVHcx9-oaNIAG6dRuIu

Slave_SQL_Running: No mysql同步故障解决方法
http://kerry.blog.51cto.com/172631/277414/
相关文章
相关标签/搜索