mysql主从复制原理:

 Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。

请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。

1.1 mysql支持的复制类型:

  (1):基于语句的复制:  在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。  

           一旦发现没法精确复制时,   会自动选着基于行的复制。    

  (2):基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持

  (3):混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。

1.2 . 复制解决的问题

        MySQL复制技术有以下一些特点:

        (1)    数据分布 (Data distribution )

        (2)    负载平衡(load balancing)

        (3)    备份(Backups)

        (4)    高可用性和容错行 High availability and failover

 1.3 复制如何工作

       整体上来说,复制有3个步骤:  

      (1)    master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);

      (2)    slave将master的binary log events拷贝到它的中继日志(relay log);

      (3)    slave重做中继日志中的事件,将改变反映它自己的数据。


该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。


下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。


SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。


此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。


数据库的复制的特点:

特点:异步,结果最终一致,由网络IO延迟决定。

注意:主服务器的版本一定要比从服务器版本低或者一样,如果做主主复制,两者版本必须一样。



mysql主从复制配置,步骤如下:

1、主从服务器分别作以下操作:

 1.1、版本一致或者主比从版本低

 1.2、初始化表,并在后台启动mysql

 1.3、修改root的密码


2、修改主服务器master:

  #vi /etc/my.cnf

      [mysqld]

      log-bin=mysql-bin   //[必须]启用二进制日志

      server-id=2         //[必须]服务器唯一ID,默认是1


      binlog-do-db=wordpress是表示只备份wordpress。

      binlog_ignore_db=mysql表示忽略备份mysql。

      不加binlog-do-db和binlog_ignore_db,那就表示备份全部数据库。

      log-slave-updates //把更新的记录写到二进制文件中;

      slave-skip-errors //跳过错误,继续执行复制;


3、修改从服务器slave:

  #vi /etc/my.cnf

      [mysqld]

      relay-log=relay-bin   //[必须]启用中继日志

      server-id=3         //[必须]服务器唯一ID,默认是1


      log-bin=mysql-bin    //如果从服务器不做其他服务器的主mysql,可以不用启用


4、重启两台服务器的mysql

  /etc/init.d/mysql restart


5、在主服务器上建立帐户并授权slave:

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

  mysql>GRANT REPLICATION SLAVE ON *.* to 'copy'@'%' identified by 'passwd'; //一般不用root帐号,“%”表示所有客户端都可能连,一般为slave 内网ip地址,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。

  flush privileges;


6、登录主服务器的mysql,查询master的状态(主服务器一个线程:dump )

  mysql>show master status;

  +------------------+----------+--------------+------------------+

  | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |

  +------------------+----------+--------------+------------------+

  | mysql-bin.000004 |      308 |              |                  |

  +------------------+----------+--------------+------------------+

  1 row in set (0.00 sec)

  注:执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化


7、配置从服务器Slave:(从服务器两个线程)

  mysql>change master to master_host='master_ip',master_user='copy',master_password='passwd',

        master_log_file='mysql-bin.,000004',master_log_pos=308;   //注意不要断开,“308”无单引号。如果是主是新的mysql,则后面两项不用加。


  Mysql>start slave;    //启动从服务器复制功能


8、检查从服务器复制功能状态:


  mysql> show slave status\G


  *************************** 1. row ***************************


               Slave_IO_State: Waiting for master to send event

                  Master_Host: 192.168.2.222  //主服务器地址

                  Master_User: copy           //授权帐户名,尽量避免使用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

              Replicate_Do_DB:

         Replicate_Ignore_DB:

          Replicate_Do_Table:

      Replicate_Ignore_Table:

     Replicate_Wild_Do_Table:

 Replicate_Wild_Ignore_Table:

                  Last_Errno: 0

                  Last_Error:

                Skip_Counter: 0

         Exec_Master_Log_Pos: 189874339

             Relay_Log_Space: 189874686

             Until_Condition: None

              Until_Log_File:

               Until_Log_Pos: 0

          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#复制延迟时间

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: 20

1 row in set (0.00 sec)


注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。


以上操作过程,主从服务器配置完成。


9、主从服务器测试:


主服务器Mysql,建立数据库,并在这个库中建表插入一条数据,在从服务器能看到新加的数据库及记录,就代表已经成功了。



10、完成:

   编写一shell脚本,用nagios监控slave的两个“yes”,如发现只有一个或零个“yes”,就表明主从有问题了,发短信警报吧。

   脚本例子:

#!/bin/bash

declare -a    slave_is  #声明一个数组

slave_is=($(cd /usr/local/nagios; /usr/local/mysqlec/bin/mysql -uuser -ppasswd  -e "show slave status \G"|grep Running |awk '{print $2}'))

if [ "${slave_is[0]}" = "Yes" -a "${slave_is[1]}" = "Yes" ]

    then

    echo "OK -EC slave is running"

    exit 0

else

    echo "Critical -EC slave is error"

    exit 2

fi





常见错误:

如果是slave_io_running no了,那么就我个人看有三种情况,一个是网络有问题,连接不上,像有一次我用虚拟机搭建replication,使用了nat的网络结构,就是死都连不上,第二个是有可能my.cnf有问题。最后一个是授权的问题,replication slave和file权限是必须的。