Bootstrap

docker搭建mysql主从同步

主从复制的作用

1、做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
2、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
3、读写分离,使数据库能支撑更大的并发。在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度。

1.搭建主数据库

docker run -d -p 3306:3306 -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql-docker mysql:5.7

mysql主数据库 配置文件配置

docker exec -it mysql-docker /bin/bash
cd /etc/mysql/mysql.conf.d
vim mysqld.cnf
添加以下配置
log-bin=/var/lib/mysql/mysql-bin  #开启mysql的binlog日志功能
server-id=1 # 节点ID,确保唯一
binlog_format=MIXED  #binlog日志格式,mysql默认采用statement,建议使用mixed
expire_logs_days=30  #binlog过期清理时间
max_binlog_size=100m #binlog每个日志文件大小
max_allowed_packet = 1G
net_buffer_length = 1048576
sync_binlog = 1         #控制数据库的binlog刷到磁盘上去 , 0 不控制,性能最好,1每次事物提交都会刷到日志文件中,性能最差,最安全
binlog-ignore-db=mysql #不生成日志文件的数据库,多个忽略数据库可以用逗号拼接,或者 复制这句话,写多行
slave-skip-errors = all #跳过从库错误

保存退出

2.搭建从数据库

docker run -d -p 3307:3306 -v /home/mysql_slave1/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql_slave1 mysql:5.7

mysql.cnf 配置

server-id = 2
log-bin=/var/lib/mysql/mysql-bin
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
slave_parallel_workers = 4
slave_parallel_type= logical_clock #基于组提交的并行复制方式 DATABASE:默认值,基于库的并行复制方式
master_info_repository=TABLE #是否将主状态和连接信息记录到 FILE(master.info)或a TABLE (mysql.slave_master_info)
relay_log_info_repository=TABLE #取决于服务器的 relay_log_info_repository 设置(FILE或 TABLE)
sync_master_info=1 #若master-info-repository为FILE,当设置为0,则每次sync_master_info事件都会刷新到磁盘,默认为10000次刷新到磁盘;若master-info-repository为TABLE,当设置为0,则表不做任何更新,设置为1,则每次事件会更新表 #默认为10000
sync_relay_log = 1 #默认为10000,即每10000次sync_relay_log事件会刷新到磁盘。为0则表示不刷新,交由OS的cache控制。
sync_relay_log_info = 1 #若relay_log_info_repository为FILE,当设置为0,交由OS刷新磁盘,默认为10000次刷新到磁盘;若relay_log_info_repository为TABLE,且为INNODB存储,则无论为任何值,则都每次evnet都会更新表。

relay_log_recovery=ON #当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的

重启两个mysql,让配置生效

3.导出主数据库数据

docker exec -it mysql-docker /bin/bash
mysqldump -uroot -p123456 --all-databases >/all_databases.sql  #导出主数据库的数据

4.把数据导入从数据库

docker exec -it mysql_slave1 /bin/bash
mysql -uroot -p123456 </all_databases.sql

5.主从同步配置

1.进入master的数据库,为master创建复制用户

CREATE USER repl_user IDENTIFIED BY 'repl_passwd';

2.赋予该用户复制的权利

grant replication slave on *.* to 'repl_user'@'%'  identified by 'repl_passwd';
FLUSH PRIVILEGES;

3.查看master的状态

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000018 | 10306799 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

4.进入slave数据库配置

CHANGE MASTER TO 
MASTER_HOST = '192.168.1.107',  
MASTER_USER = 'repl_user', 
MASTER_PASSWORD = 'repl_passwd',
MASTER_PORT = 3306,
MASTER_LOG_FILE='mysql-bin.000018',
MASTER_LOG_POS=10306799,
MASTER_RETRY_COUNT = 60,
MASTER_HEARTBEAT_PERIOD = 10000;
# MASTER_LOG_FILE='mysql-bin.000018',#与主库File 保持一致
# MASTER_LOG_POS=10306799, #与主库Position 保持一致

启动从库slave进程

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

查看状态

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.107
                  Master_User: repl_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000018
          Read_Master_Log_Pos: 10263291
               Relay_Log_File: mysql-relay-bin.000004
                Relay_Log_Pos: 17258
        Relay_Master_Log_File: mysql-bin.000018
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: mysql.%,test.%,information_schema.%
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 10263291
              Relay_Log_Space: 17465
              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: 1
                  Master_UUID: e5377b78-2250-11eb-9b38-0242ac110005
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 60
                  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
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

以下状态表示启动成功
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

Seconds_Behind_Master: 0

6.Slave_SQL_Running: No mysql同步故障解决方法

解决办法II:
重新进入slave数据库配置

slave stop;
CHANGE MASTER TO 
MASTER_HOST = '192.168.1.107',  
MASTER_USER = 'repl_user', 
MASTER_PASSWORD = 'repl_passwd',
MASTER_PORT = 3306,
MASTER_LOG_FILE='***',
MASTER_LOG_POS=***,
MASTER_RETRY_COUNT = 60,
MASTER_HEARTBEAT_PERIOD = 10000;
start slave;

解决办法II(不建议使用):

mysql> slave stop;
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql>start slave;

7.半同步复制

默认的主从复制方式是异步复制,有可能存在数据丢失的问题(主节点挂了,从节点还没来得及读主节点的binlog)。半同步复制则是来解决该问题,用来保证节点之间的数据一致性。

mysql让master在某一个时间点等待slave节点的ack消息,接收到ack后才进行事务提交,这也是半同步复制的基础,了解半同步之前我们可以先回顾一下主从辅助master节点事务的处理过程。众所周知,mysql的事务是分为两阶段提交,处理流程大概如下:

当master不需要关注slave是否接受到binlog事件时,即为传统的主从复制,当master需要在第三步等待slave返回ack时,即为半同步复制(after-commit)。还有另外一种是增强半同步。

半同步复制配置
master配置

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.20 sec)

mysqld.cnf 配置

# master半同步复制配置
plugin-load="rpl_semi_sync_master=semisync_master.so"
rpl_semi_sync_master_enabled=1
# 半同步超时时间,默认10s,半同步复制发生超时会转为异步复制
rpl_semi_sync_master_timeout=10000

slave配置

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.06 sec)

mysqld.cnf 配置

# slave半同步复制配置
# 半同步复制配置
plugin-load="rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_slave_enabled=1
;