mysql · 2022-03-03 0

docker 搭建 mysql 8.0 主从复制

1.拉取镜像

docker pull mysql:8.0

2.创建网络

创建网络,使得容器都在此网络内,容器间可以通过容器名互联

docker network create -d bridge my-net

3.创建容器

docker run -d --net my-net -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql-3307 mysql:8.0
docker run -d --net my-net -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql-3308 mysql:8.0

4.修改配置文件

配置文件是:/etc/mysql/my.conf

mysql-3307 是主节点,配置文件为:

[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL
# 同一局域网内注意要唯一
server-id=100  
# 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-master-bin
# 二级制日志格式,有三种 row,statement,mixed
binlog-format=ROW
# 同步的数据库名称,如果不配置,表示同步所有的库
# binlog-do-db=数据库名

mysql-3308 是从节点,配置文件为:

[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL
# 设置server_id,注意要唯一
server-id=101  
# 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin   
# relay_log配置中继日志
relay_log=mysql-relay-bin  
# 设置为只读,该项如果不设置,表示slave可读可写
read_only=1

修改完配置文件,重启容器

5.配置用户

进入 mysql-3307,配置用户 repl

create user 'repl'@'%' identified with mysql_native_password by '123456';
grant replication slave on *.* to 'repl'@'%';

6.查看主节点状态

使用 show master status 命令,查看主节点状态

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

7.配置从节点

change master to master_host='172.18.0.2', master_user='repl', master_password='123456', master_port=3306, master_log_file='mysql-master-bin.000001', master_log_pos=826, master_connect_retry=30;

master_host :Master库的地址,指的是容器的独立ip,可以通过
master_port:Master的端口号,指的是容器的端口号
master_user:用于数据同步的用户
master_password:用于同步的用户的密码
master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒

8.查看从节点状态

使用 start slave,开启主从同步(注意:关闭是stop slave,如果改变同步参数需先关闭)

使用 show slave status 命令,查看从节点状态,当 Slave_IO_Running 和 Slave_SQL_Running 为 Yes 时,表示成功

mysql> show slave status G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.18.0.2
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: mysql-master-bin.000001
          Read_Master_Log_Pos: 2402
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 1907
        Relay_Master_Log_File: mysql-master-bin.000001
             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: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 2402
              Relay_Log_Space: 2116
              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: 100
                  Master_UUID: 715bbc9e-9ab9-11ec-8725-0242ac120002
             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: 86400
                  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: 
       Master_public_key_path: 
        Get_master_public_key: 0
            Network_Namespace: 
1 row in set, 1 warning (0.00 sec)

ERROR: 
No query specified

Master_Log_File,Read_Master_Log_Pos 记录了IO thread读到的当前master binlog文件和位置, 对应master的binlog文件和位置。

Relay_Log_File,Relay_Log_Pos记录了SQL thread执行到relay log的那个文件和位置,对应的是slave上的relay log文件和位置。

Relay_Master_Log_File,Exec_Master_Log_Pos记录的是SQL thread执行到master binlog的文件和位置,对应的master上binlog的文件和位置。

9.主从复制流程

mysql 的 binlog 日志作用是用来记录 mysql 内部增删等对mysql数据库有更新的内容的记录(对数据的改动),对数据库查询的语句如show,select开头的语句,不会被binlog日志记录。用于数据库的主从复制,以及增量恢复。

mysql

MySQL主从复制之前我们需要先启动master数据库然后再启动slave数据库,然后在slave数据库中执行start slave;,执行完成之后,流程就如下了:

执行change master to ...stop slave、达到sync_master_info的值时,会写入 master.info 文件(或slave_master_info表)

mysql> show variables like '%master%';
+------------------------------------------------+-------+
| Variable_name                                  | Value |
+------------------------------------------------+-------+
| binlog_rotate_encryption_master_key_at_startup | OFF   |
| master_info_repository                         | TABLE |
| master_verify_checksum                         | OFF   |
| sync_master_info                               | 10000 |
+------------------------------------------------+-------+
4 rows in set (0.00 sec)

master_info_repository 有两个值,分别是file和table,该参数决定了slave记录master的状态,如果参数是file,就会创建master.info文件,如果参数值是table,就在mysql中创建slave_master_info的表。

1)如果master_info_repository=file,sync_master_info=N,其中N>0,那么slave就会在每N个事件后,使用fdatasync()方式同步到master.info文件中。如果sync_master_info=N,其中N=0,那么MySQL就会把状态信息写入到OS Cache中,需要等待操作系统同步。
2)如果master_info_repository=table,sync_master_info=N,如果N>0,那么slave就会在,每N个事件后,更新mysql.slave_master_info表,如果N=0,那么mysql.slave_master_info表将永远不会更新。

主从复制流程:

  1. slave 的IO线程会读取mastr.info文件(或slave_master_info表)中配置好的主库信息,比如说存放的有:master数据库的用户名、密码、端口、还有master的binlog索引位置;
  2. 拿到信息之后就带着信息去链接master的主库IO线程
  3. 当主库的IO线程先检查slave传过来的配置信息是否正确,如果正确,就拿着slave传过来的binlog索引位置和master库的binlog文件中最后一个索引位置进行对比,如果一致就陷入等待状态,等待Master的binlog索引位置更新;
  4. 如果不一致就把slave传过来的binlog索引位置往后的所有SQL语句包括最后一条SQL语句的索引位置发送个给slave的IO线程;
  5. slave的IO线程拿到信息之后,先把master传过来的binlog索引在slave的master.info文件(或slave_master_info表)中进行更新;
  6. 然后再把master传过来的SQL语句写入到relay中继日志文件中,然后继续循环执行第二个步骤;
  7. slave的SQL线程会一直持续的观察relay中继日志文件中是否有改动,如果没有就继续监听;
  8. 如果发现relay中继日志文件中有变动,那么就获取变动的内容转换为SQL语句,并且把SQL语句在 slave 的数据库中进行执行