概括的讲,主从同步就是,从库先导入主库的某一个位置点的备份,然后根据主库的binlog日志再不停地通过增量执行增删改,达到与主库一致。
工作原理:
- Master开启binlog功能(日志功能);
- 把Master某个时间点的整库备份导入到Slave中,备份时最好使用master-data=1这个参数;
- 在Master上分配一个REPLICATION SLAVE的帐号用于同步;
- MASTER包含一个IO进程,SLAVE的MySQL包括了IO进程和SQL进程(但这两个进程没有关联);
- SLAVE发起复制请求并提供MASTER_LOG_FILE和MASTER_LOG_POS。
- MASTER的主进程通过验证后,把任务交给IO进程,并根据MASTER_LOG_FILE和MASTER_LOG_POS开始,不停的向SLAVE发送来自binlog的后续日志(主动推送);
- SLAVE的IO进程接收到这些日志后,存放到relay日志文件中,并在master.info文件中登记最新接收到的MASTER_LOG_FILE和MASTER_LOG_POS。
- SLAVE的SQL进程循环地从relay日志读取并执行,使SLAVE的库达到与MASTER库一致;
具体部署步骤
- 开启Master的binlog功能;
在my.cnf中,配置log-bin=路径+前缀;如
log-bin = /disk2/mysql_multi_instances/3308/mysql-bin
MySQL会在 /disk2/mysql_multi_instances/3308/这个目录下,生产binlog数据文件,前缀是mysql-bin,后缀是六位数字。
2. 备份Master数据库
[[email protected] ~]# mysqldump -uroot -p -h 127.0.0.1 -P 3308 -F -A -B -x --add-drop-database --events --master-data=1|gzip >3308.sql.gz
-F切割binlog(可选)
-A全部数据库
--add-drop-database 在CREATE DATABASE前插入DROP DATABASE,适合于整库备份的情况
-x锁表
-B可以指定多个DBNAME,但如果整库备份的话,也可以不指定,甚至不写
--events 导出时包含事件排程(event scheduler),如果不加,可能会有警告;总而言之可加可不加。
--master-data最最重要的参数,在导出的内容中插入
CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000101‘, MASTER_LOG_POS=3658;
这类语句,据说SLAVE可以根据这句自行判断MASTER_LOG_FILE和MASTER_LOG_POS,可是在我的测试中发现还是需要手工指定一下;anyway,设定这个参数你可以很容易查到FILE和POS,何乐而不为,这个参数有两个值1和2,1就是上面的效果,2就是把上面的效果注释掉作为参考。FILE和POS也可以在MASTER上查到
mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000101 | 3658 | | | +------------------+----------+--------------+------------------+
3. Master上分配帐号用于同步
mysql> grant replication slave on *.* to [email protected]‘192.168.5.%‘ identified by ‘jet‘;
注意是 replication slave的权限(两个单词)
4. SLAVE把整库的备份文件导入库文件。
[[email protected] ~]# gzip -d 3308.sql.gz
[[email protected] ~]# mysql -uroot -p < 3308.sql
5. SLAVE上编写CHANGE MASTER语句
mysql> CHANGE MASTER TO
MASTER_HOST=‘192.168.5.103‘,
MASTER_USER=‘rep‘,
MASTER_PASSWORD=‘jet‘,
MASTER_PORT=3308,
MASTER_LOG_FILE=‘mysql-bin.000101‘,
MASTER_LOG_POS=107;
注意,这些资料必须严格核对。
7. SLAVE上执行slave start,然后查看状态
mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.5.103 Master_User: rep Master_Port: 3308 Connect_Retry: 60 Master_Log_File: mysql-bin.000101 Read_Master_Log_Pos: 3658 Relay_Log_File: mysqld-relay-bin.000024 Relay_Log_Pos: 252 Relay_Master_Log_File: mysql-bin.000101 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: 3658 Relay_Log_Space: 554 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: 1 row in set (0.00 sec)
其中最重要的是Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes,这两个都YES,才代表同步会话正确连接;在测试中,我在CHANGE MASTER语句中没有手工指定FILE和POS,启动slave后,只有Slave_IO_Running: Yes,而Slave_SQL_Running: No,这样的同步是有问题的,同时也会在状态界面上显示执行失败的SQL语句;后来我把slave stop,并重新指定FILE和POS,再slave start就正常了。
另外,也可以看到SLAVE上会多了master.info文件和relay日志文件
[[email protected] ~]# ll /var/lib/mysql/{master.info,mysqld-relay*} -rw-rw----. 1 mysql mysql 73 Jan 24 22:12 /var/lib/mysql/master.info -rw-rw----. 1 mysql mysql 302 Jan 24 22:12 /var/lib/mysql/mysqld-relay-bin.000023 -rw-rw----. 1 mysql mysql 252 Jan 24 22:12 /var/lib/mysql/mysqld-relay-bin.000024 -rw-rw----. 1 mysql mysql 52 Jan 24 22:12 /var/lib/mysql/mysqld-relay-bin.index
其实,那些relay日志文件也是binlog文件,可以用mysqlbinlog查看;而master.info文件则是文本文件,用于登记关于master的一些参数
[[email protected] ~]# less /var/lib/mysql/master.info
15
mysql-bin.000101
3658
192.168.5.103
rep
jet
3308
60
0
0
0