Mysql主从复制原理与实践

Mysql主从复制原理:

1.Mysql支持单双向、链式级联、异步复制。可以一主一从,也可以一主多从。

2.链式级联中的从是下级从的主。类似A-->B-->C-->D。

3.主从复制配好后,数据库的更新必须在主服务器上进行,以免造成主从冲突。

4.主从服务器架构可实现对用户的请求实现读写分离。从处理用户的select,主处理update,insert,delete等更新。以此保持主从实时同步。

5.可以把从服务器根据业务来拆分。

6.mysql主从复制是异步复制。master与slave之间三个线程参与完成,其中两个线程(IO和SQL)在slave,另一个线程(IO)在master端。

7.首先必须打开master的Binlog(Mysql-bin.xxxxxx)功能,因为整个复制过程实际上就是slave从master端获取Binlog日志,然后在slave自身上以相同的顺序执行binlog日志中所记录的各种操作。


下面简单描述下mysql主从复制过程(Binlog中不包含select内容):

1.slave服务器上执行 start slave 开启主从复制开关。

2.此时。slave服务器的IO线程会通过在master上授权的复制用户请求连接master服务器,并请求从指定的Binlog日志文件的指定位置之后的Binlog的日志内容。

3.master服务器接收到来自slave服务器的IO线程的请求后,master服务器上负责复制的IO线程根据slave服务器的IO线程请求的信息读取指定Binlog日志文件的指定位置之后的Binlog的日志信息,然后返回给slave端的IO线程。返回信息除了日志内容外,还有本次返回的日志内容后在master服务器端的新的Binlog文件名称以及在Binlog中的指定位置。

4.当slave的IO线程收到来自master的IO线程发送的日志内容及日志文件及位置点后,将Binlog日志内容依次写入到slave自身的relaylog(中继日志)文件(mysql-relay-bin.xxxxxx)的最末端,并将新的Binlog文件名和位置记录到master-info文件中,以便下一次读取master的新Binlog日志时能够告诉master需要从新Binlog日志的那个文件哪个位置开始请求新的Binlog日志内容。

5.slave服务器的sql线程会实时的检测本地relay log 中新增加了日志内容,然后把这些内容解析成master曾经执行的sql语句,并在自身slave上按语句的顺序执行sql语句。

6.这样 就可以确保在master和slave执行了同样的sql语句。


实践:

主:10.240.210.41 从:10.240.210.42

1.主从启动mysql

2.主库操作:

修改my.cnf

添加server-id=41

    log-bin=(=后可以不填)

grant replication slave on *.* to 'rep'@'10.240.210.%' identified by '123';


3.检测下select user,host from mysql.user;

show grants for rep@'10.240.210.%';


4.锁表(以免主从不一致):

mysql>flush tables with read lock;
mysql>show variables like '%timeout%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| connect_timeout            | 10    |
| delayed_insert_timeout     | 300   |
| innodb_lock_wait_timeout   | 50    |
| innodb_rollback_on_timeout | OFF   |
| interactive_timeout        | 28800 |
| net_read_timeout           | 30    |
| net_write_timeout          | 60    |
| slave_net_timeout          | 3600  |
| table_lock_wait_timeout    | 50    |
| wait_timeout               | 28800 |
+----------------------------+-------+
10 rows in set (0.00 sec)


5.查看主库状态(记录binlog位置):

mysql> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| mysqld-bin.000001 |      340 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

6.导出数据库数据(新开窗口 当前窗口保留):

 mysqldump -uroot -p -A -B | gzip >/server/backup/mysql_bak.$(date +%F).sql.gz


7.检测倒库期间数据库有没有被操作:

mysql> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| mysqld-bin.000001 |      340 |              |                  |
+-------------------+----------+--------------+------------------+

8.解锁主库(恢复可写):

mysql>unlock table;


9.从库操作:

修改my.cnf

添加server-id=42

    #log-bin=(=后可以不填)

10.解压并在从库恢复主库的sql:

gzip -d mysql_bak.2014-12-04.sql.gz
mysql -uroot -p < mysql_bak.2014-12-04.sql

11.从库运行:

cat | mysql -uroot -p <<EOF
CHANGE MASTER TO
MASTER_HOST='10.240.210.41',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123',
MASTER_LOG_FILE='mysqld-bin.000001',
MASTER_LOG_POS=340;
EOF

12.启动从库:

mysql -uroot -p -e "start slave;"

13.展示从库同步状态(主库一定要关闭iptables 否则从库会连不上):

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.240.210.41
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysqld-bin.000001
          Read_Master_Log_Pos: 489
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 401
        Relay_Master_Log_File: mysqld-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: 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: 489
              Relay_Log_Space: 557
              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:

14.测试

主库建数据库 查看从库


总结:将首次获取binlog名称和位置的过程写成脚本如下 方便省事:

[root@lvs_master ~]# cat mysql_bak.sh 
#!/bin/bash
#首次获取binlog名称和位置 by wujie
MYUSER=root
MYPASS="123"
MAIN_PATH=/server/backup
DATA_PATH=/server/backup
LOG_FILE=${DATA_PATH}/mysqllog_`date +%F`.log
DATA_FILE=${DATA_PATH}/mysql_backup_`date +%F`.sql.gz

MYSQL_PATH=/usr/bin/
MYSQL_CMD="$MYSQL_PATH/mysql -u$MYUSER -p$MYPASS"
MYSQL_DUMP="$MYSQL_PATH/mysqldump -u$MYUSER -p$MYPASS -A -B --flush-logs --single-transaction -e"

$MYSQL_CMD -e "flush tables with read lock;"
echo "------show master status result-----" >>$LOG_FILE
$MYSQL_CMD -e "show master status;" >> $LOG_FILE
${MYSQL_DUMP} | gzip > $DATA_FILE
$MYSQL_CMD -e "unlock tables;"
mail -s "mysql slave log" [email protected] < $LOG_FILE


你可能感兴趣的:(master)