初始环境
有一台机器A安装了MySQL5.7.20作为主数据库服务器,它已经运行了一段时间,具有小规模的数据。一个Web应用使用Spring+JPA+Hibernate来访问这个数据库。
目标
在机器B上安装MySQL作为slave数据库服务器,与主数据库形成主从复制架构。修改Web应用使读写分离,所有读操作走slave数据库,所有写操作走master数据库。
步骤
1.安装备库
在机器B上安装MySQL5.7.20。参考官方文档https://dev.mysql.com/doc/refman/5.7/en/linux-installation-rpm.html
2.创建复制账号
在主库上创建一个用户,并赋予合适的权限。备库将用这个用户连接到主库并读取其二进制日志。
mysql> grant replication slave,replication client on *.* to repl identified by 'Welcome1';
3. 配置主库和备库
在主库上打开二进制日志,并指定一个唯一的服务器ID。在主库的my.cnf文件中增加或修改如下内容:
server-id = 43(服务器id,每台机器要唯一,最好用IP最后一位)
log_bin = mysql-bin(这是主服务器,必须开启log_bin,这句就是开启了)
binlog_format = mixed(混合比较好,还有statements,rows)
binlog_do_db = master(需要同步的数据库,如果多个数据库,重复这个配置)
binlog_ignore_db = mysql(排除不需要同步的数据库,如果多个数据库,重复这个配置)
expire_logs_days = 7(二进制日志自动删除或过期的天数。默认为0,不删除)
slave_skip_errors = 1062 (跳过指定的错误,1062指主键重复,1032是主从数据库不一致, 请百度更多)
binlog_cache_size = 1M (为每个session分配的内存)
查看二进制日志文件是否已经在主库上建立。
mysql> show master status;
Empty set (0.00 sec)
说明二进制日志文件还没有建立。需要重启MySQL服务,
sh-4.1# /sbin/service mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
再次查看,发现二进制日志文件已经建立。
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)
备库也需要在my.cnf中增加类似的配置,然后也需要重启MySQL服务。
log_bin=mysql-bin
server_id=45
relay_log=/var/lib/mysql/mysql-relay-bin
log_slave_updates=1 (表示slave将复制事件写进自己的二进制日志)
read_only=1 (表示从节点只能读,不能写)
4. 启动复制
我们要告诉备库如何连接到主库并重放其二进制日志。
mysql> change master to master_host='host1',
-> master_user='repl',
-> master_password='Welcome1',
-> master_log_file='mysql-bin.000001',
-> master_log_pos=0;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
master_log_pos设置为0,说明要从日志开头读起。然后可以使用show slave status来检查复制是否正确执行。
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: slc05ida.us.oracle.com
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
......
Seconds_Behind_Master: NULL
......
1 row in set (0.00 sec)
发现Slave_IO_State,Slave_IO_Running和Slave_SQL_Running三列显示当前备库复制还没开始运行。而且日志开头是4,不是0。
运行下面的命令开始执行复制:
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
再次查看
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: slc05ida.us.oracle.com
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 154
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
......
1 row in set (0.01 sec)
在主库上执行show processlist\G可以看到复制线程。
mysql> show processlist\G
*************************** 5. row ***************************
Id: 9
User: repl
Host: slc10giz.us.oracle.com:40508
db: NULL
Command: Binlog Dump
Time: 93
State: Master has sent all binlog to slave; waiting for more updates
Info: NULL
5 rows in set (0.00 sec)
在备库上执行show processlist\G可以看到一个I/O线程和一个SQL线程。
mysql> show processlist\G
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: starting
Info: show processlist
*************************** 2. row ***************************
Id: 5
User: system user
Host:
db: NULL
Command: Connect
Time: 152
State: Waiting for master to send event
Info: NULL
*************************** 3. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 151
State: Slave has read all relay log; waiting for more updates
Info: NULL
3 rows in set (0.00 sec)
5. 从主库克隆数据
配置了上面的主从复制之后,我们发现备库没有获得主库原有的数据。因为以上的主从复制只是同步配置主从复制之后发生的事件。我们需要用其他方法克隆主库原来的数据。这里我们使用mysqldump。它只是用于数据库中只有InnoDB表的时候。
-bash-4.1$ /usr/bin/mysqldump --single-transaction --all-databases --master-data=1 --host=host1 -ufmwhatool -pfmwhatool| mysql --host=host2 -uroot -pWelcome1
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 3021 (HY000) at line 22: This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first.
mysqldump: Got errno 32 on write
看来我们需要先把主从复制关掉。
mysql> stop slave;
Query OK, 0 rows affected (0.03 sec)
-bash-4.1$ /usr/bin/mysqldump --single-transaction --all-databases --master-data=1 --host=1 -ufmwhatool -pfmwhatool| mysql --host=host2 -uroot -pWelcome1
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
这次没有报错。
过了一会儿,我们查看备库,发现数据已经克隆过去了。
再用start slave;命令打开主从复制。
在主库中某个Table里插入记录,就会发现从库里的这个Table里马上就有这条记录了。
OK,到此主从复制成功。