前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【DB 系列】基于 Docker 的 MySQL 主从复制搭建和配置

【DB 系列】基于 Docker 的 MySQL 主从复制搭建和配置

作者头像
框架师
发布2022-09-02 11:48:18
3840
发布2022-09-02 11:48:18
举报
文章被收录于专栏:墨白的Java基地墨白的Java基地

前言

为什么基于 Docker 搭建 MySQL ?

  • 在 Linux 服务器中以系统安装 MySQL 比较繁琐
  • 一台服务器可以独立运行多个 Docker 容器
  • Docker 容器之间相互独立,有独立 ip,互不冲突
  • Docker 使用步骤简便,启动容器在秒级别

环境准备:

主库

  • 运行主库
代码语言:javascript
复制
$ docker run --restart=always -d --name=mysql --privileged=true -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -v /usr/local/mysql/my.cnf:/etc/mysql/my.cnf -v /usr/local/mysql/logs:/var/log/mysql -v /usr/local/mysql/data:/var/lib/mysql -v /etc/localtime:/etc/localtime mysql
  • 配置主库

修改挂载的配置文件

代码语言:javascript
复制
[root@mobai data]# cat /usr/local/mysql-master/my.cnf 
[mysqld]  
# 设置 server_id, 注意要唯一
server-id=2022
# 开启二进制日志功能 
log-bin=mysql-master
# relay_log 配置中继日志
relay_log=edu-mysql-relay-bin

从库

  • 运行从库
代码语言:javascript
复制
$ docker run --restart=always -d --name=mysql --privileged=true -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -v /usr/local/mysql/my.cnf:/etc/mysql/my.cnf -v /usr/local/mysql/logs:/var/log/mysql -v /usr/local/mysql/data:/var/lib/mysql -v /etc/localtime:/etc/localtime mysql
  • 配置从库
代码语言:javascript
复制
[root@mobaijun mysql]# cat /usr/local/mysql/my.cnf 
[mysqld]
server-id=100  
# 开启二进制日志功能
log-bin=mysql-bin

重启主从库

代码语言:javascript
复制
$ docker restart 容器 id

注意事项:

首先在主从没有生效的时候,要保持两台服务器数据库、表相同,数据相同

主从库用户权限分配

分别在两台服务器 MySQL 8 中创建用户,授予权限。

  • 查询所有用户
代码语言:javascript
复制
SELECT `user`
	,
`HOST` 
FROM
	mysql.`user`;
  • 在主从库分别重复一下步骤
代码语言:javascript
复制
# 创建同步用户
CREATE USER 'april-synchronize' @'%' IDENTIFIED BY 'april-synchronize123!@';
# 分配用户权限(全部权限)
GRANT ALL PRIVILEGES ON *.* TO 'april-synchronize' @'%';
# 也可也分配增删改查权限和 slave 权限
GRANT SELECT, DELETE,UPDATE,INSERT,REPLICATION SLAVE, REPLICATION CLIENT,REPLICATION_SLAVE_ADMIN ON *.* TO 'april-synchronize' @'%';
# 授予复制账号 REPLICATION CLIENT 权限,复制用户可以使用 SHOW MASTER STATUS, SHOW SLAVE STATUS 和 SHOW BINARY LOGS 来确定复制状态。
# 授予复制账号 REPLICATION SLAVE 权限,复制才能真正地工作。
-------------------------------------------------------------------------------------------------------------
# 刷新权限
FLUSH PRIVILEGES;
# 查询用户权限
SHOW GRANTS FOR 'april-synchronize' @'%';
-------------------------------------------------------------------------------------------------------------
# 删除用户
DROP USER 'april-synchronize' @'%';

主从链接

  • 在主库命令行进入 MySQL
代码语言:javascript
复制
$ show master status;
代码语言:javascript
复制
+---------------------+----------+--------------+------------------+-------------------+
| File                | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+----------+--------------+------------------+-------------------+
| mysql-master.000003 |   312957 |              |                  |                   |
+---------------------+----------+--------------+------------------+-------------------+

File 和 Position 字段的值后面将会用到,在后面的操作完成之前,需要保证主库不能做任何操作,否则将会引起状态变化,File 和 Position 字段的值变化。

  • 从库

进入命令行,执行以下内容

代码语言:javascript
复制
CHANGE MASTER TO master_host = '172.17.0.3',
master_user = 'april-synchronize',
master_password = 'april-synchronize123!@',
master_port = 3306,
master_log_file = 'mysql-master.000003',
master_log_pos = 312957,
master_connect_retry = 30;

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

  • 在从库中的 mysql 终端执行 show slave status \G; 用于查看主从同步状态。
代码语言:javascript
复制
mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.17.0.2
                  Master_User: april-master
                  Master_Port: 3309
                Connect_Retry: 30
              Master_Log_File: mysql-master.000003
          Read_Master_Log_Pos: 164307
               Relay_Log_File: d856863ac1d2-relay-bin.000002
                Relay_Log_Pos: 329
        Relay_Master_Log_File: mysql-master.000003
             Slave_IO_Running: NO
            Slave_SQL_Running: NO
              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: 164307
              Relay_Log_Space: 546
              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: 2022
                  Master_UUID: a993626d-1e9a-11ed-a66e-0242ac110003
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Replica 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: 

正常情况下,Slave_IO_Running 和 Slave_SQL_Running 都是 No,因为我们还没有开启主从复制过程。

  • 使用 start slave 开启主从复制过程,然后再次查询主从同步状态 show slave status \G;

如果在开启主从的过程中显示权限不足,按照上面步骤添加 REPLICATION_SLAVE_ADMIN 权限,然后刷新即可。报错信息如下:

代码语言:javascript
复制
Access denied; you need (at least one of) the SUPER or REPLICATION_SLAVE_ADMIN privilege(s) for this operation
  • 修改权限,添加 REPLICATION_SLAVE_ADMIN
代码语言:javascript
复制
GRANT SELECT, DELETE,UPDATE,INSERT,REPLICATION SLAVE, REPLICATION CLIENT, REPLICATION_SLAVE_ADMIN ON *.* TO 'luban-synchronize' @'%';
  • 查看主从状态
代码语言:javascript
复制
$ show slave status \G;

类似下图

Slave_IO_Running 和 Slave_SQL_Running 都是 Yes,说明主从复制已经开启。此时可以测试数据同步是否成功。如果需要主从双向同步,在主库重复以上操作即可,一主多从,多主多从操做都是一样的,注意用户账号密码 / 及服务器 IP 端口正确。

  • 双向同步最终效果

异常排查

如果出现异常,重点观察从库主从状态的异常日志,按照日志提示做出修改。

上图原因就是 IP 不通导致的,两台非局域网服务器,比如线上的服务器,以 Docker 启动后,拿外网 IP + 端口,非 Docker IP

其他可能出现的问题:

  • 网络不通 检查 ip, 端口
  • 密码不对 检查是否创建用于同步的用户和用户密码是否正确
  • pos 不对 检查主库的 Position

主从测试

非常简单,在主库创建一个数据库,然后检查从库是否存在此数据库。

完整的主备流程图

最后让我们来看一下,一个 update 语句在节点 A 执行,然后同步到节点 B 的完整流程图。

可以看到:主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写入 binlog。 备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程,专门用于服务备库 B 的这个长连接。 一个事务日志同步的完整过程是这样的:

1、在备库 B 上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码、以及要从哪个位置开始请求 binlog,这个位置包含文件名和日志偏移量。 2、在备库 B 上执行 start slave 命令,这时侯备库会启动两个线程,io_thread 和 sql_thread。其中, io_thread 负责与主库建立连接。 3、主库 A 校验完用户名、密码后,开始按照备库 B 传过来的位置,从本地读取 binlog,发给 B。 4、备库 B 拿到 binlog 后,写到本地文件,称为中转日志(relay log)。 5、sql_thread 读取中转日志,解析日志里的命令,并执行。

参考文章

基于 Docker 的 MySQL 主从复制搭建及原理(真正弄懂) | MySQL 技术论坛

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 环境准备:
    • 主库
      • 从库
      • 重启主从库
      • 注意事项:
      • 主从库用户权限分配
      • 主从链接
      • 异常排查
      • 主从测试
      • 完整的主备流程图
      • 参考文章
      相关产品与服务
      容器镜像服务
      容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档