Mysql主从同步(AB复制)
实验背景:
1.配置2台MySQL服务器,实现 主-->从 同步。
2.其中Master服务器允许SQL查询、写入,Slave服务器只允许SQL查询
实验方案:
使用2台RHEL 6.4虚拟机,其中192.168.4.10是MySQL主服务器,负责提供同步源;另一台
192.168.4.20作为MySQL从服务器,通过调取主服务器上的binlog日志,在本地重做对应的库、表,实现与
主服务器的AB复制(同步)。
提前为两台MySQL服务器安装好MySQL-server、MySQL-Client软件包,并为数据库用户root修改密码;Linux客户机上则只需安装MySQL-Client软件包即可。
实验实现:
1.初始化现有库
为了在启用binlog日志及同步之前保持主、从库的一致性,建议进行初始化――备份主服务器上现有的库,然后导入到从服务器上。
当现有库、表都采用MyISAM引擎时,可执行离线备份、恢复,这样更有效率;否则,可通过mysqldump等工具来实现库的导出、导入。
1)备份MySQL Master(192.168.4.10)上现有的库
如果服务器已经启用binlog,建议对日志做一次重置,否则可忽略:
# mysql -u root -p
password://以数据库管理员登陆
mysql> RESET MASTER; //重置binlog日志
mysql> quit //退出mysql> 环境
以备份mysql库、test库为例,导出操作如下:
#mysqldump -uroot -p -B mysql test>/root/mytest.sql
password:
//-B 导出多个
#ls //确认备份结果
2)在MySQL Slave(192.168.4.20)上导入备份的库
先清理目标库,避免导入时冲突。主要是采用InnoDB引擎的库,授权库mysql多采用MyISAM引擎,可不做清理。
# mysql -u root -p
Enter password: //以数据库用户root登入
.. ..
mysql> DROP DATABASE test; //删除test库
Query OK, 0 rows affected (0.03 sec)
mysql> quit //退出mysql> 环境
Bye
使用scp工具下载备份文件:
#scp /dbsvr1:/root/mytest.sql .///远程复制
root@dbsvr1's password: //验证对方系统用户root的口令
执行导入操作:
#mysql -uroot -p <mysql.sql
password :
导入成功后,可重新登入 mysql> 环境,确认清理的目标库已恢复:
mysql> show databases;
2.配置MySQL Master(主服务器,192.168.4.10)
1)修改/etc/my.cnf配置,重新启动MySQL服务程序
指定服务器ID号、允许日志同步:
[root@dbsvr1 mysql]# vim /etc/my.cnf
[mysqld]
log_bin=dbsvr1-bin //启用binlog日志,并指定文件名前缀
server_id = 10 //指定服务器ID号
innodb_flush_log_at_trx_commit=1 //优化设置
sync-binlog=1 //允许日志同步
重启mysql服务:
[root@dbsvr1 ~]# service mysql restart
Shutting down MySQL.. [确定]
Starting MySQL.. [确定]
2)新建一个备份用户,授予复制权限(授权用户不一定是本地用户)
需要的权限为REPLICATION SLAVE,允许其从Slave服务器访问:
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replicater'@'192.168.4.%' IDENTIFIED BY 'pwd123'; //用户授权,设置密码
Query OK, 0 rows affected (0.04 sec)
3)检查Master服务器的同步状态
在已经初始化现有库的情况下,查看MASTER状态,记录下当前的日志文件名、偏移的位置(下面SLAVE发起复制时需要用到):
mysql> SHOW MASTER STATUS\G
File: dbsvr1-bin.000002 //记住当前的日志文件名
Position: 334 //记住当前位置
3.配置MySQL Slave(从服务器,192.168.4.20)
1)修改/etc/my.cnf配置,重新启动MySQL服务程序
指定服务器ID号、允许日志同步:
[root@dbsvr2 ~]# vim /etc/my.cnf
[mysqld]
log_bin=dbsvr2-bin //启动SQL日志,并指定文件名前缀
.server_id = 20 //指定服务器ID号,不要与Master的相同
innodb_flush_log_at_trx_commit=1 //优化设置
sync-binlog=1 //允许日志同步
log_slave_updates=1 //记录从库更新,便于实现“主-从-从”链式复制
配置完成后,重启mysql服务:
# service mysql restart
2)登入 mysql> 环境,发起同步操作
mysql> CHANGE MASTER TO MASTER_HOST='192.168.4.10', //指定主服务器
-> MASTER_USER='replicater', //同步用户和密码
-> MASTER_PASSWORD='pwd123',
-> MASTER_LOG_FILE='dbsvr1-bin.000002', //对应Master的日志文件
-> MASTER_LOG_POS=334; //对应Master的日志偏移位置(可以从主的show master status 查看)
Query OK, 0 rows affected, 2 warnings (0.12 sec)
然后执行START SLAVE(较早版本中为SLAVE START)启动复制:
mysql> START SLAVE; //启动复制
通过上述连接操作,MASTER服务器的设置信息自动存为master.info文件,以后每次MySQL服务程序时会自动调用并更新,无需重复设置。查看master.info文件的开头部分内容,可验证相关设置:
3)检查Slave服务器的同步状态
通过SHOW SLAVE STATUS语句可查看从服务器状态,确认其中的IO线程、SQL线程正常运行,才能成功同步:
mysql> SHOW SLAVE STATUS\G //查看slave的状态
......
Slave_IO_Running: Yes //IO线程应该已运行
Slave_SQL_Running: Yes //SQL线程应该已运行
//2个yes表示成功
4.测试主从同步效果
1)在Master上操作数据库、表、表记录
新建newdb库、newtable表,随意插入几条表记录:
mysql> CREATE DATABASE newdb; //新建库newdb
Query OK, 1 row affected (0.04 sec)
mysql> USE newdb; //切换到newdb库
Database changed
mysql> CREATE TABLE newtable(id int(4)); //新建newtable表
Query OK, 0 rows affected (0.14 sec)
mysql> INSERT INTO newtable VALUES(1234),(5678); //插入2条表记录
Query OK, 2 rows affected (0.05 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM newtable; //确认表数据
+------+
| id |
+------+
| 1234 |
| 5678 |
+------+
2 rows in set (0.00 sec)
2)在Slave上确认自动同步的结果
直接切换到newdb库,并查询newtable表的记录,应该与Master上的一样,这才说明主从同步已经成功生效:
mysql> USE newdb; //直接切换到newdb库
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> SELECT * FROM newtable; //输出表记录
+------+
| id |
+------+
| 1234 |
| 5678 |
+------+
2 rows in set (0.02 sec)
3)在Master服务器上可查看Slave主机的信息
mysql> SHOW SLAVE HOSTS;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 20 | | 3306 | 10 | 2f62f59d-7e71-11e3-bb5d-000c299422aa |
+-----------+------+------+-----------+--------------------------------------+
5.将Slave服务器设为只读
一般来说,为了避免写入冲突,采用主、从复制结构时,不应该允许用户从Slave执行数据库写入操作,这样会导致双方数据的不一致性。
正因为如此,我们可以把Slave数据库限制为只读模式,这种情况下有SUPER权限的用户和SLAVE同步线程才能写入。相关验证操作及效果可参考以下过程。
1)新建一个测试用户rwuser(不能用root测试)
在Master上建立即可,会自动同步到Slave上:
mysql> GRANT all ON newdb.* TO rwuser@localhost IDENTIFIED BY '1234567';
Query OK, 0 rows affected (0.14 sec)
2)未启用只读前,验证从Slave写入
在Slave上以rwuser登入(不要用root哦):
[root@dbsvr2 ~]# mysql -u rwuser -p
mysql> CREATE TABLE booker(id int(12)); //成功创建booker表
Query OK, 0 rows affected (0.08 sec)
mysql> SHOW TABLES;
+-----------------+
| Tables_in_newdb |
+-----------------+
| booker |
| newtable |
+-----------------
但是在Master上却看不到,导致主、从上的newdb出现不一致:
完成上述验证后,在Slave上删除booker表,确保双方一致:
2)修改/etc/my.cnf文件,重载配置
[root@dbsvr2 ~]# vim /etc/my.cnf
[mysqld]
.. ..
read_only=1 //启动只读模式
[root@dbsvr2 ~]# service mysql restart //重启服务
Shutting down MySQL.. [确定]
Starting MySQL... [确定]
3)再次在Slave上验证数据库写入操作
仍然是以rwuser登入(不要用root哦)来验证,当尝试创建新表时会被拒绝:
mysql> CREATE TABLE booker(id int(12)); //新建表的写入操作失败
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
1.4 扩展
1.为Slave指定报告给Master的主机名
1)在Slave上启用 --report-host 选项
修改/etc/my.cnf配置文件,添加“report_host=主机名”即可启用,以便向Master报告本机的主机名:
[root@dbsvr2 ~]# vim /etc/my.cnf
[mysqld]
.. ..
report_host=dbsvr2 //报告指定的主机名
[root@dbsvr2 ~]# service mysql restart //重启服务
Shutting down MySQL.. [确定]
Starting MySQL... [确定]
2)在Master上查看效果
当执行SHOW SLAVE HOSTS语句时,输出的信息中会包含Slave提供的名称:
mysql> SHOW SLAVE HOSTS;
+-----------+--------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+--------+------+-----------+--------------------------------------+
| 20 | dbsvr2 | 3306 | 10 | 2f62f59d-7e71-11e3-bb5d-000c299422aa |
+-----------+--------+------+-----------+--------------------------------------+
1 row in set (0.00 sec)
2.指定哪些库参与主从复制
有两种途径,任选其中一种即可:
?在Master上限制,采用binlog-do-db、binlog-ignore-db选项,指定对哪些库记录或不记录二进制日志,不记录的自然就无法被Slave读取,从而也就相当于不参与同步。
?在Slave上限制,采用replicate-do-db、replicate-ignore-db选项,指定对哪些库执行复制或排除复制。
上述设置参数中,记录与不记录属于互斥选项,不要同时设置;复制与不复制也是互斥选项,不要同时设置。
当设置多条replicate-do-db或replicate-ignore-db时,需要特别注意:这种情况下Master的跨库操作(比如UPDATE 库名.表名 .. ..)不会被同步,从而易导致后续同步报错中断。要解决这个问题,可改用(或合用)以下两个选项:
?replicate-wild-do-table=库名.%
?replicate-wild-ignore-table=库名.%
以只同步mysql、test库为例,相关操作及效果可参考下列过程。
1)在Slave上调整设置,只同步mysql库、test库
.[root@dbsvr2 ~]# vim /etc/my.cnf
.[mysqld]
.. ..
replicate_do_db=mysql //同步mysql库
replicate-wild-do-table=mysql.% //含跨库更新
replicate_do_db=test //同步test库
replicate-wild-do-table=test.% //含跨库更新
//其他未指定的库将被忽略
[root@dbsvr2 ~]# service mysql restart //重启服务
Shutting down MySQL.. [确定]
.Starting MySQL... [确定]
2)在Master上分别操作test库、newdb库,
在test库中新建synctb表:
mysql> CREATE TABLE test.synctb(id int(4),name varchar(12));
Query OK, 0 rows affected (0.14 sec)
mysql> INSERT INTO test.synctb VALUES(1,'Jerry'); //插入一条测试记录
Query OK, 1 row affected (0.03 sec)
mysql> SELECT * FROM test.synctb; //确认表记录
+------+-------+
| id | name |
+------+-------+
| 1 | Jerry |
+------+-------+
1 row in set (0.00 sec)
在newdb库中新建notsynctb表:
mysql> CREATE TABLE newdb.notsynctb(id int(4),name varchar(12));
Query OK, 0 rows affected (0.09 sec)
mysql> INSERT INTO newdb.notsynctb VALUES(1,'Mike'); //插入一条测试记录
Query OK, 1 row affected (0.01 sec)
mysql> SELECT * FROM newdb.notsynctb; //确认表记录
+------+------+
| id | name |
+------+------+
| 1 | Mike |
+------+------+
1 row in set (0.00 sec)
3)在Slave上观察同步结果
Master上对test库的操作已同步到Slave:
mysql> select * from test.synctb;
+------+-------+
| id | name |
+------+-------+
| 1 | Jerry |
+------+-------+
1 row in set (0.00 sec)
Master上对newdb库的操作被Slave忽略,未执行同步:
mysql> SELECT * FROM newdb.notsynctb;
ERROR 1146 (42S02): Table 'newdb.notsynctb' doesn't exist
实验总结:
1、主从服务器my.cnf的参数配置,在生产环境中,还可以根据需要设置更详细的同步选项。比如,指定当主、从网络中断时的重试超时时间(slave-net-timeout=60 )等,具体可参考MySQL手册。
2、一旦启用SLAVE复制,当需要修改MASTER信息时,应先执行STOP SLAVE停止复制,然后重新修改、启动复制。
3、若START SLAVE直接报错失败,请检查CHANGE MASTER相关设置是否有误,纠正后再
重试;若IO线程或SQL线程有一个为“No”,则应检查服务器的错误日志,分析并排除故障后重启主从复制。
4、.指定哪些库参与主从复制
有两种途径,任选其中一种即可:
?在Master上限制,采用binlog-do-db、binlog-ignore-db选项,指定对哪些库记录或不记录二进制日志,不记录的自然就无法被Slave读取,从而也就相当于不参与同步。
?在Slave上限制,采用replicate-do-db、replicate-ignore-db选项,指定对哪些库执行复制或排除复制。