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