1. 资源规划。申请并启动3个节点,一主两从,统一安装好MySQL-5.7(参见 https://www.notion.so/MySQL-080ad77acae04a7fbdd1caddfc3881af)(MySQL服务很小,可以让主机开机自启动: chkconfig mysqld on)

    并作出如下规划:

    主机名    IP             角色
    mysql-1  192.168.1.25   主(master/source) 
    mysql-2  192.168.1.26   从(slave/replica)
    mysql-3  192.168.1.27   从(slave/replica)
    

    MySQL简单读写分离架构.png

  2. 配置主从节点的binlog开启和server_id

    vim /etc/my.cnf 追加:

    log-bin=mysql-bin
    server-id=1
    
  3. 重启主节点。执行 service mysqld restart

  4. 创建用来做主从同步的用户,并赋予主从同步的权限. 在主节点(source)上执行:

    mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'P@ssw0rd';
    mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
    

    注:安全起见,应该像官网那样限定一个域名,如“example.com”或者“192.168.1.%”

  5. 主节点上刷写所有表的数据并阻止所有的写操作,以保证下一步的数据准确性,但执行完了之后不要退出这个mysql提示符:

    mysql> FLUSH TABLES WITH READ LOCK;
    
  6. 重启一个ssh连接,并也登陆到这个主节点的MySQL命令行。然后执行 SHOW MASTER STATUS 命令,获取当前主节点的状态:

    mysql> SHOW MASTER STATUS;
    +------------------+----------+--------------+------------------+-------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000001 |      587 |              |                  |                   |
    +------------------+----------+--------------+------------------+-------------------+
    

    记录下 mysql-bin.000001 和 587 这两个值,他们分别代表log文件存放位置和当前的偏移量。

  7. (选做,如果主库已有数据而从库是新的)退出第二个MySQL命令行,然后执行:

    mysqldump --all-databases --master-data > dbdump.db
    

    拷贝全量数据

  8. 在主节点第一个登录的mysql命令行中执行:

    mysql> UNLOCK TABLES;
    

    释放锁

  9. 在从节点上修改 /etc/my.cnf, 追加:

    server-id=x
    

    其中,x=2,3,4等唯一标识出主机就可以

  10. 重启(启动)各个从节点。执行 service mysqld restart

  11. 在各个从节点执行如下命令,从库通过执行这个命令连接主库,并提供了连接的用户的一切条件:usernbame、password、主节点IP、port、binlog文件和读取位置(这里最后两个配置项用到了第5步记录下来的数值):

    mysql> CHANGE MASTER TO
        -> MASTER_HOST='192.168.1.25',
        -> MASTER_USER='repl',
        -> MASTER_PASSWORD='P@ssw0rd',
        -> MASTER_LOG_FILE='mysql-bin.000001',
        -> MASTER_LOG_POS=587;
    

    单行版,方便修改执行:

    CHANGE MASTER TO MASTER_HOST='192.168.1.25',MASTER_USER='repl',MASTER_PASSWORD='P@ssw0rd',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=587;
    
  12. (选做,如果主库已有数据而从库是新的)把步骤7的文件拷贝到从节点,并执行如下命令恢复数据快照:

    mysql < fulldb.dump
    
  13. (选做)往已经运行的集群中添加新的从节点:https://dev.mysql.com/doc/refman/5.7/en/replication-howto-additionalslaves.html

  14. 验证。执行:

    mysql> show slave status\\G;
    

    如果输出中以下两项均为“YES”,则说明已经配置运行成功:

    ...
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    ...
    

    注意⚠️:如果各台机器的server UUID有重复的,则会造成Slave_IO_Running: NO. 这就要修改auto.cnf文件,使之各不相同: vim /var/lib/mysql/auto.cnf

    https://blog.csdn.net/cug_jiang126com/article/details/46846031

  15. 进一步验证。在主库上面执行:

    mysql> create database test;
    

    新建一个名为“test”的数据库,然后在从库上显示所有数据库可得:

    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | test               |
    +--------------------+
    5 rows in set (0.00 sec)
    

    则说明主库所做的更改已经同步到了从库。然后再去检查主库的binLog文件 ( /var/lib/mysql/mysql-bin.00000x ),则发现其中有如下乱码:

    ...
    std^D!^@!^@^H^@^L^Atest^@test^@create database test^U=²$
    ...
    

    所以从库的test数据库应该就是通过这一条binlog的复制而被创建出来的。乱码是因为默认binlog格式是mixed

  16. 再进一步验证。在主库上执行如下几条命令,建表、插入数据并查询,然后得到结果:

    mysql> use test;
    mysql> create table `student` (`id` int, `name` varchar(10), primary key (`id`));
    mysql> insert into student (id, name) value (1, 'zhangsan');
    mysql> select * from student;
    +----+----------+
    | id | name     |
    +----+----------+
    |  1 | zhangsan |
    +----+----------+
    

    然后在从库执行 mysql> select * from student; 也会得到与上面相同的结果。

注意事项

虽然主从同步已经配置好并运行起来了,但是客户端一旦往从库里面做写操作,则还是会出现人为造成的主从不一致,这个时候就要保证数据库集群所接到的写请求都要作用在主库上。例如:

直接登陆从库,执行

insert into student (id, name) value (2, 'lisi');