暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL主从同步复制实践

叶同学专栏 2021-04-16
399

环境描述

目前机器192.168.43.175(sdw3)上已经安装mysql5.7版本,使用的是InnoDB引擎。现在新机器192.168.43.176(sdw4)配置成为sdw3的从库。

操作过程

1.主库上启用二进制日志,配置文件添加参数,重启生效

[root@sdw3]/usr/local/mysql# cat my.cnf 
[mysqld]
port = 13306
secure_file_priv =
socket=/usr/local/mysql/mysql.sock

log-bin=mysql-bin
server-id=17513306

2.在主库中创建复制账号,允许从库来访问

grant replication slave,replication client on *.* to replic_user identified by '123456';

3.主库全量备份数据库

3.1 在主库上运行命令锁表,并查看当前的binlog
的文件名和Position
,后面配置从库时参数用到

mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

3.2 新建另外会话窗口,使用mysqldump 命令备份数据库

mysqldump --master-data=2 --single-transaction --all-databases > /data/mysqldata/mysqldump.sql

参数解释:

master-data=2 会生成被注释掉的 CHANGE MASTER TO 语句,默认值是1,会生成自动执行的语句

single-transaction 参数表示制作一个一致性的备份集,对于 InnoDB ,制作一致性备份集的时候不会锁表,仍然可以读写数据

3.3 mysqldump 命令执行完毕之后,在主库上原来的会话连接里,解锁表

UNLOCK TABLES;

4.部署从库

详细过程见之前文章:MYSQL安装笔记

5.编辑从库配置文件

[mysqld]
port = 13306
secure_file_priv =
socket=/usr/local/mysql/mysql.sock

log_bin = mysql-bin
server_id = 17613306
log_slave_updates = 1
read_only = 1

参数解释

log_bin=mysql-bin :建议主从配置一样的名字

log_slave_updates=1 :log_slave_updates 决定了是否将从主库接收的更新写入从库自身的二进制日志里。将这个值设置为 1 ,是方便以后以将这个从库提升为主库后,根据需要再配置一个从库,也方便数据恢复。当然,设置这个变量也有弊端。如更大的 I/O 写入,不容易发现错误等

read_only=1 ,只有 SUPER 权限的用户才可以修改从库数据

6.从库导入 dump 文件

mysql < /data/mysqldata/mysqldump.sql

7.执行同步命令,成为从库

RESET SLAVE;
CHANGE MASTER TO
MASTER_HOST='192.168.43.175',
MASTER_PORT=13306,
MASTER_USER='replic_user',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE=' mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;

8.查看主从同步状态

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.43.175
                  Master_User: replic_user
                  Master_Port: 13306
                Connect_Retry: 60
              Master_Log_File:  mysql-bin.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: sdw4-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File:  mysql-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: Yes
...
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

关键看这以下这两个参数,同时为YES就表示同步正常

Slave_IO_Running: No
Slave_SQL_Running: Yes

这里的Slave_IO_Running
为NO,查看日志是:

Could not find first log file name in binary log index file

经检查是同步命令MASTER_LOG_FILE指定的文件名有空格,再重新执行一下:

stop slave;
CHANGE MASTER TO
MASTER_HOST='192.168.43.175',
MASTER_PORT=13306,
MASTER_USER='replic_user',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;

这时同步变成正常了:

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.43.175
                  Master_User: replic_user
                  Master_Port: 13306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 154
               Relay_Log_File: sdw4-relay-bin.000003
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

9.测试主从数据同步

主库上操作,建表并查询数据

mysql> use test;
mysql> create table test(a int,b varchar(100));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test values(1,'a');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(2,'b');
Query OK, 1 row affected (0.00 sec)
mysql> create index test_index_a on test(a);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

从库上查看表及数据已同步

mysql> use test;
Database changed
mysql> select * from test;
+------+------+
| a    | b    |
+------+------+
|
    1 | a    |
|    2 | b    |
+------+------+
2 rows in set (0.00 sec)

MySQL同步策略

异步复制

上面搭建的是异步模式,即主库将数据库修改事件写入到自己的binlog ,不会管从库的状态是否正常或延迟时间等, 所以当主库崩溃要主从切换时,有可能从库上的数据不是最新的 。

延时同步复制

MySQL 同步在快速的网络中是毫秒级的,如果有误操作,从库也会马上变更,可能会带来风险。
可考虑配置一个延迟复制的副本, 其原理是从库收到主库的binlog之后,再等待指定的秒数之后再执行。

从库上执行命令为:(延时60秒同步)

CHANGE MASTER TO MASTER_DELAY=60;

半同步复制

  • 当主库执行一个更新操作事物时,提交操作会被阻止直到至少有一个半同步的复制从库确认依据接收到本次更新操作,主库的提交操作才会继续。

  • 半同步从库在写入事件到中继日志( relay log )时,刷新到磁盘后才确认接收。

  • 如果没有任何从库发送确认消息而导致超时时,半同步复制会转换成异步复制。

  • 当至少一个半同步从库追赶上主库,主库又会自动切换到半同步模式。

实现过程

1.主库安装半同步模块并启动
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled = 1;
mysql> set global rpl_semi_sync_master_timeout = 2000;

mysql> show global variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
|
 rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 2000       |
|
 rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
|
 rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+

rpl_semi_sync_master_timeout:配置主库等待多少毫秒时间来保证接收备库的确认消息,当超时这个时间时,半同步变成异步方式。

想永久有效需要写到配置文件中:

[mysqld]
...
rpl_semi_sync_master_enabled = 1;
rpl_semi_sync_master_timeout = 2000; --单位毫秒

2.从库安装半同步模块并启用
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled = 1;

mysql> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+

从库需要重新连接主库,半同步才会生效

mysql> stop slave io_thread;
mysql> start slave io_thread;

3.主库上查看半同步状态
mysql> show global status like '%rpl%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
|
 Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
|
 Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
|
 Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
|
 Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
|
 Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
|
 Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
|
 Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+

确认Rpl_semi_sync_master_clients
为1和Rpl_semi_sync_master_status
为ON

测试

主库建表,耗时0.01秒

mysql> create table tmp1(a int);
Query OK, 0 rows affected (0.01 sec)

从库停止半同步

mysql> set global rpl_semi_sync_slave_enabled =0;
Query OK, 0 rows affected (0.00 sec)

mysql> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

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

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

主库第一次执行建表需要2.01秒,第二次建表则变成0.01秒,表示半同步模式变成异步模式

mysql> create table tmp12(int);
Query OK, 0 rows affected (2.01 sec)

mysql> create table tmp123(int)
;
Query OK, 0 rows affected (0.01 sec)


文章转载自叶同学专栏,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论