1、要求mysql
一、配置现有的一台MySQL服务器为主服务器,另外一台做为其从服务器sql
二、其中Master服务器容许查询和写入,Slave只容许查询数据库
2、方案vim
使用3台RHEL6.5虚拟机,以下图所示。其中192.168.4.10是MySQL主服务器,负责提供同步源;192.168.4.20是MySQL从服务器,通过调取主服务器上的binlog日志,在本地重作对应的库、表,实现与主服务器的同步;192.168.4.100是客户机,用来登陆数据库验证试验结果,也能够不用客户机而直接在从和主上操做数据库。服务器
3、实现网络
1、准备工做socket
为两台MySQL服务器安装MySQL-server、MySQL-client软件包并为数据库修改root密码,客户机上只需安装MySQL-client。这里用的软件包包含在了 MySQL-5.6.15-1.el6.x86_64.rpm-bundle.tar里(点击可下载)ide
若是是两台服务器是克隆的,那么它们mysql服务器的server-uuid值可能相同,能够用下面两条命令查看一下工具
[root@slave ~]# cat /var/lib/mysql/auto.cnf测试
[auto]
server-uuid=c8b982e3-336b-11e4-9780-525400f9a647
要是相同,能够用uuidgen从新生成一个uuid,以替换auto.cnf里的server-uuid
[root@client ~]# uuidgen
bad15423-2ec5-4204-85b5-8d4027e05408
[root@master ~]# cat /var/lib/mysql/auto.cnf
[auto]
server-uuid=bad15423-2ec5-4204-85b5-8d4027e05408
修改配置文件并重启mysql服务以启用binlog日志
[root@master ~]# vim /etc/my.cnf
... ...
log-bin=mysql-bin
[root@master ~]# service mysql restart
Shutting down MySQL.... [肯定]
Starting MySQL.... [肯定]
在master上建立grade库来假设主服务器上已有的数据
[root@master ~]# mysql -uroot -p
Enter password: //以root身份登陆,输入root用户密码
... ...
mysql> create database grade;
Query OK, 1 row affected (0.00 sec)
mysql> create table grade.math ( name varchar(20),score float(4,1));
Query OK, 0 rows affected (1.36 sec)
mysql> insert into grade.math values ( "jim" ,80.5);
Query OK, 1 row affected (0.17 sec)
mysql> select * from grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
+------+-------+
1 row in set (0.00 sec)
2、配置主服务器master (192.168.4.10)
1)修改配置文件/etc/my.cnf,指定服务器ID号、容许日志同步,重启mysql服务
[root@master mysql]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql //数据库主目录
socket=/var/lib/mysql/mysql.sock
user=mysql
server_id=10 //指定服务器ID号
log-bin=mysql-bin //启用binlog日志并指定前缀
sync-binlog=1 //容许日志同步
... ...
[root@master mysql]# service mysql restart
Shutting down MySQL.. [肯定]
Starting MySQL. [肯定]
2)新建一个备份用户,授予复制权限,容许其从slave服务器访问
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replicater'@'192.168.4.%' IDENTIFIED BY 'pwd123';
Query OK, 0 rows affected (0.07 sec)
3)检查master服务器的同步状态
mysql> SHOW MASTER STATUS\G;
*************************** 1. row ***************************
File: mysql-bin.000002 //当前的日志文件名
Position: 334 //当前记录的位置
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
3、配置从服务器slave(192.168.4.20)
1)修改配置文件/etc/my.cnf,指定服务器ID号,重启mysql服务。在生产环境中还能够根据更MySQL手册设置更详细的选项。
[root@slave mysql]# vim /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
server_id=20
log-bin=slave //启用binlog日志并指定前缀
... ...
[root@slave mysql]# service mysql restart
Shutting down MySQL.. [肯定]
Starting MySQL. [肯定]
2)登陆mysql,发起同步
经过CHANGE MASTER语句指定MASTER服务器的IP地址、同步用户名/密码、起始日志文件、偏移位置
mysql> CHANGE MASTER TO MASTER_HOST='192.168.4.10',
-> MASTER_USER='replicater',
-> MASTER_PASSWORD='pwd123',
-> MASTER_LOG_FILE='mysql-bin.000001', //对应Master的日志文件
-> MASTER_LOG_POS=1; ////对应Master的日志偏移位置
若是起始日志文件、偏移位置按照上面的写法,那么能够同步主服务器上自启用binlog日志以来对数据库所作的操做。
也能够在主服务器上SHOW MASTER STATUS\G; 按照当前状态填写,这时只同步master从这一刻之后对数据库的操做,之前的库和表不会同步,能够选择手动同步。当现有库、表都采用MyISAM引擎时,可执行离线导入导出,这样更有效率。不然可以使用mysqldump等工具来实现 库的导入导出。
而后启动slave
mysql> START SLAVE;
Query OK, 0 rows affected (0.05 sec)
一旦启用SLAVE复制,当须要修改MASTER信息时,应先执行STOP SLAVE中止复制,而后从新修改、启动复制。
经过上述链接操做,MASTER服务器的设置信息自动存为master.info文件,之后每次MySQL服务程序时会自动调用并更新,无需重复设置。查看master.info文件的开头部份内容,可验证相关设置:
[root@slave mysql]# head /var/lib/mysql/master.info
23
mysql-bin.000001 //对应Master的日志文件
120
192.168.4.10 //master的ip地址
replicater //与master同步的用户名
pwd123 //密码
3306 //端口
60
0
mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.4.10
Master_User: replicater
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 334
Relay_Log_File: slave-relay-bin.000003
Relay_Log_Pos: 497
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes //IO线程应该已运行
Slave_SQL_Running: Yes //SQL线程应该已运行
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: 334
Relay_Log_Space: 1283
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: 10
Master_UUID: bad15423-2ec5-4204-85b5-8d4027e05408
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
若START SLAVE直接报错失败,请检查CHANGE MASTER相关设置是否有误,纠正后再重试;若IO线程或SQL线程有一个为“No”,则应检查服务器的错误日志,分析并排除故障后重启主从复制。
4、测试主从同步效果
在主服务器上受权一个用户,会自动同步到slave上,用户用于在客户端(192.168.4.100)登陆:
mysql> GRANT ALL ON grade.* TO "user01"@"192.168.4.%" IDENTIFIED BY "pwd123" ;
Query OK, 0 rows affected (0.12 sec)
在客户端上登陆从库
在从上发现grade库已经同步过来
[root@client ~]# mysql -h192.168.4.20 -uuser01 -ppwd123
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| grade |
| test |
+--------------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
+------+-------+
1 row in set (0.00 sec)
1)在客户端用user01登陆Master数据库
在grade库的math表里随意插入几条表记录:
[root@client 桌面]# mysql -h 192.168.4.10 -uuser01 -ppwd123
... ...
mysql> INSERT INTO grade.math VALUES ("tom",78),("lily",90);
Query OK, 2 rows affected (0.25 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
| tom | 78.0 |
| lily | 90.0 |
+------+-------+
3 rows in set (0.00 sec)
2)在Slave上确认自动同步的结果
直接查询math表的记录,应该与Master上的同样,这才说明主从同步已经成功生效:
[root@client 桌面]# mysql -h 192.168.4.20 -uuser01 -ppwd123
... ...
mysql> SELECT * FROM grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
| tom | 78.0 |
| lily | 90.0 |
+------+-------+
3 rows in set (0.00 sec)
3)在Master服务器上可查看Slave主机的信息
mysql> SHOW SLAVE HOSTS;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 20 | | 3306 | 10 | c8b982e3-336b-11e4-9780-525400f9a647 |
+-----------+------+------+-----------+--------------------------------------+
1 row in set (0.00 sec)
五、将slave服务器设为只读
通常来讲,为了不写入冲突,采用主、从复制结构时,不该该容许用户从Slave执行数据库写入操做,这样会致使双方数据的不一致性。
正由于如此,咱们能够把Slave数据库限制为只读模式,这种状况下有SUPER权限的用户和SLAVE同步线程才能写入。相关验证操做及效果可参考如下过程。
1)未启用只读前,验证从slave写入
在客户端上以user01身份登陆slave,并写入数据:
[root@client 桌面]# mysql -h 192.168.4.20 -uuser01 -ppwd123
... ...
mysql> INSERT INTO grade.math VALUES ("bob",60);
Query OK, 1 row affected (0.09 sec)
在slave上能够看到新插入的数据:
mysql> SELECT * FROM grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
| tom | 78.0 |
| lily | 90.0 |
| bob | 60.0 |
+------+-------+
4 rows in set (0.00 sec)
mysql> QUIT
Bye
可是在master上却看不到,致使主、从上的math表数据不一致
[root@client 桌面]# mysql -h 192.168.4.10 -uuser01 -ppwd123
... ...
mysql> SELECT * FROM grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
| tom | 78.0 |
| lily | 90.0 |
+------+-------+
3 rows in set (0.00 sec)
mysql> quit
Bye
完成上述验证后,在slave上删除刚刚插入的记录,确保主从数据一致
[root@client 桌面]# mysql -h 192.168.4.20 -uuser01 -ppwd123
... ...
mysql> DELETE FROM grade.math WHERE name="bob";
Query OK, 1 row affected (0.11 sec)
mysql> SELECT * FROM grade.math;
+------+-------+
| name | score |
+------+-------+
| jim | 80.5 |
| tom | 78.0 |
| lily | 90.0 |
+------+-------+
3 rows in set (0.00 sec)
mysql> QUIT
Bye
2)修改slave的/etc/my.cnf文件,重启mysql服务
[root@slave mysql]# vim /etc/my.cnf
[mysqld]
... ...
read_only=1 //启动只读模式
[root@slave mysql]# service mysql restart
Shutting down MySQL.. [肯定]
Starting MySQL.. [肯定]
3)再次在slave上验证数据库写入操做
在client(192.168.4.100)上以user01用户登陆从库
[root@client 桌面]# mysql -h 192.168.4.20 -uuser01 -ppwd123
... ...
mysql> USE grade; //切换到grade库,
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> INSERT INTO math VALUES ("lucy",99);
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement //表的写操做失败,提示数据库运行在只读模式下
4、扩展
指定哪些库参与主从复制
有两种途径:
u 在Master上限制,采用binlog-do-db、binlog-ignore-db选项,指定对哪些库记录或不记录二进制日志,不记录的天然就没法被Slave读取,从而也就至关于不参与同步。
u 在Slave上限制,采用replicate-do-db、replicate-ignore-db选项,指定对哪些库执行复制或排除复制。
上述设置参数中,记录与不记录属于互斥选项,不要同时设置;复制与不复制也是互斥选项,不要同时设置。
当设置多条replicate-do-db或replicate-ignore-db时,须要特别注意:这种状况下Master的跨库操做(好比UPDATE 库名.表名 .. ..)不会被同步,从而易致使后续同步报错中断。要解决这个问题,可改用(或合用)如下两个选项:
replicate-wild-do-table=库名.%
replicate-wild-ignore-table=库名.%
以只同步test库为例,相关操做及效果参考以下:
1)在slave上修改/etc/my.cnf文件,只同步test库
[root@slave mysql]# vim /etc/my.cnf
[mysqld]
... ...
replicate-do-db=mysql //同步mysql库
replicate-wild-do-table=mysql.% //含跨库更新,可是跨的库只容许在能够同步的库列表里,好比在这里只容许在test库或mysql库里更新mysql库
replicate_do_db=test
replicate_wild_do_table=test.%
//其余未指定的库将被忽略
... ...
[root@slave mysql]# service mysql restart
Shutting down MySQL.... [肯定]
Starting MySQL.. [肯定]
2)在master上分别操做test库、grade库
在test库中新建t1表
mysql> USE mysql;
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> CREATE TABLE test.t1(id int(4),name varchar(20));
Query OK, 0 rows affected (0.93 sec)
mysql> INSERT INTO test.t1 VALUES(1,"mike");
Query OK, 1 row affected (0.17 sec)
mysql> SELECT * FROM test.t1;
+------+------+
| id | name |
+------+------+
| 1 | mike |
+------+------+
1 row in set (0.00 sec)
在grade中新建English表:
mysql> CREATE TABLE grade.English (name varchar(20),score float(3,1));
Query OK, 0 rows affected (1.15 sec)
mysql> INSERT INTO grade.English VALUES ("harry",60);
Query OK, 1 row affected (0.17 sec)
mysql> SELECT * FROM grade.English;
+-------+-------+
| name | score |
+-------+-------+
| harry | 60.0 |
+-------+-------+
1 row in set (0.00 sec)
3)在slave上观察同步结果
Master上对test库的操做已经同步到slave:
mysql> SELECT * FROM test.t1;
+------+------+
| id | name |
+------+------+
| 1 | mike |
+------+------+
1 row in set (0.00 sec)
Master上对grade库的操做被slave忽略
mysql> SELECT * FROM grade.English;
ERROR 1146 (42S02): Table 'grade.English' doesn't exist
5、/etc/my.cnf经常使用的配置选项
适用于Master服务器:
binlog-do-db=name 设置Master对那些库记日志
binlog-ignore-db=name 设置Master对那些库不记日志
适用于Slave服务器:
log-slave-updates 记录从库更新,容许链式复制(A-B-C)
relay-log=slave1-relay-bin 指定中继日志文件名
replicate-do-db=mysql 仅复制指定库,其余库将被忽略,此选项可设置多条(省略时复制全部库)
replicate-ignore-db=test 不复制哪些库,其余库将被忽略(与上一条do-db冲突,只需选用其中一条)
report-host=slave1 报告给Master的主机名或IP地址
slave-net-timeout=60 出现网络中断时,重试超时(默认为60秒)