MYSQL5.7被动模式下的主主复制

时间:2022-09-14 20:16:37

    双主模式的主动复制在真实环境中应该是比较少的,虽然mysql5.0之后增加了auto_increment_increment和auto_increment_offset选项的设置,解决了自增长主键的问题,不过允许向两台主为同时写入仍然比较危险。如果两台机器同时更改同张表上的同一笔数据,就会出现问题,更可怕的是这样的问题服务器并不会报错。这样的结构称之为主动模式的主主复制 。

    被动模式下的主主复制就是在主动主主复制的前提下,让其中一台机器设为只读状态,如果其中有一台机器出现问题的话,可能快速的切换服务器;alter操作对数据库的影响比较大,可以通过暂停其中一台的备库复制线程,在另一台上做好alter后,交换角色后再开启备库的复制线程,这样可以对服务器的影响最小化。这样的环境应该是比较常见并且重要的拓扑结构。

下面做个测试:

环境说明 :

master1 server IP:172.17.61.131

master 2 server IP:172.17.61.132

mysql version: mysql-5.7.21-linux

测试目的: 对表进行alter操作,对数据库的影响最小化。

master1:

mysql> show create table test_emp\G
*************************** 1. row ***************************
       Table: test_emp
Create Table: CREATE TABLE `test_emp` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `c1` int(10) NOT NULL DEFAULT '0',
  `c2` int(10) unsigned DEFAULT NULL,
  `c5` int(10) unsigned NOT NULL DEFAULT '0',
  `c3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `c4` varchar(90) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_c1` (`c1`),
  KEY `idx_c2` (`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=1100001 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
记住当前应到到master2的log_file和pos
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.17.61.132
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql_bin.000002
          Read_Master_Log_Pos: 1163
               Relay_Log_File: qht131-relay-bin.000003
                Relay_Log_Pos: 1118
        Relay_Master_Log_File: mysql_bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            。。。
          Exec_Master_Log_Pos: 1163
              Relay_Log_Space: 1326
              Until_Condition: None
             。。。
             Master_Server_Id: 10001
                  Master_UUID: 744cfcde-3a9b-11e8-b299-000c2900d025
             Master_Info_File: /u01/mysql/master.info
                    SQL_Delay: 0
     。。。
1 row in set (0.00 sec)

关闭master1上面的复制进程,以免master2在later table时对master有影响:

mysql> stop slave;
Query OK, 0 rows affected (0.06 sec)

master2:

mysql> alter table test_emp change c4 c6 varchar(100);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table test_emp\G
*************************** 1. row ***************************
       Table: test_emp
Create Table: CREATE TABLE `test_emp` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `c1` int(10) NOT NULL DEFAULT '0',
  `c2` int(10) unsigned DEFAULT NULL,
  `c5` int(10) unsigned NOT NULL DEFAULT '0',
  `c3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `c6` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_c1` (`c1`),
  KEY `idx_c2` (`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=1100001 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

表alter成功之后可以将应用直接切换到master2上面。

master1:

这里重新指定一下之前stop slave时的master_log_files和master_log_pos的位置,接着开启slave线程。

mysql>  change master to
    -> master_host='172.17.61.132',
    -> master_user='repl',
    -> master_password='repl',
    -> master_log_file='mysql_bin.000002',
    -> master_log_pos=1163;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show create table test_emp\G
*************************** 1. row ***************************
       Table: test_emp
Create Table: CREATE TABLE `test_emp` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `c1` int(10) NOT NULL DEFAULT '0',
  `c2` int(10) unsigned DEFAULT NULL,
  `c5` int(10) unsigned NOT NULL DEFAULT '0',
  `c3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `c6` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_c1` (`c1`),
  KEY `idx_c2` (`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=1100001 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

master1 重新开始master2的日志应用线程后,master所做的alter操作已同步到master1了,这时可以将应用的连接恢复到master1。

至此测试完成!