使用 MariaDB 10.3.4 docker 镜像设置复制

Kry*_*ten 6 mysql replication mariadb docker

我正在尝试在两个 docker 容器之间设置复制,它们都运行库存的MariaDB 10.3.4 图像(这是目前的最新版本)。当我开始了集装箱,我得到表错误代码1062(重复键)mysql.user的关键localhost-root。从站显然试图mysql.user从主站复制表并失败,因为他们都有root@localhost用户。这似乎与 Docker 无关 - 我想从头开始设置任何主/从对时会出现同样的问题。

如何设置从属设备来复制所有内容?我从头开始,所以我希望奴隶成为(或多或少)主人的完美副本。

这是设置:

我正在从docker-compose.yml文件运行容器:

version: '2'

volumes:
    dbdata:
        external: false

services:

    # the MariaDB database MASTER container
    #
    database:
        image: mariadb:10.3.4
        env_file:
            - ./env/.env.database
        volumes:
            - dbdata:/data/db
            - /etc/localtime:/etc/localtime:ro
            # mount the configuration files in the approriate place
            #
            - ./database/master/etc/mysql/conf.d:/etc/mysql/conf.d:ro
            # mount the SQL files for initialization in a place where the
            # database container will look for it on initialization; see
            # "Initializing a fresh instance" at
            # https://hub.docker.com/_/mariadb/ for details
            #
            - ./database/master/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
        ports:
            - "3306:3306"

    # the MariaDB database SLAVE container
    #
    slave:
        image: mariadb:10.3.4
        # env_file:
        #     - ./env/.env.database
        environment:
            - MYSQL_ALLOW_EMPTY_PASSWORD=yes
        volumes:
            - /etc/localtime:/etc/localtime:ro
            # mount the configuration files in the approriate place
            #
            - ./database/slave/etc/mysql/conf.d:/etc/mysql/conf.d:ro
            # mount the SQL files for initialization in a place where the
            # database container will look for it on initialization; see
            # "Initializing a fresh instance" at
            # https://hub.docker.com/_/mariadb/ for details
            #
            - ./database/slave/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
        depends_on:
            - database
Run Code Online (Sandbox Code Playgroud)

.env/.env.database文件仅公开了 MariaDB docker 映像所需的环境变量:

# the root user password
#
MYSQL_ROOT_PASSWORD=password

# the database to use
#
MYSQL_DATABASE=mydatabase
Run Code Online (Sandbox Code Playgroud)

请注意,这是我的开发环境,所以我使用了一个愚蠢的密码。

主从配置文件是从我的本地主机挂载的。

000-replication-master.sql

GRANT REPLICATION SLAVE ON *.* TO 'replicant'@'%' IDENTIFIED BY 'password';
Run Code Online (Sandbox Code Playgroud)

replication.cfg 对于主人:

[mariadb]
    log-bin
    server_id=1
    log-basename=master1

    # force binlog format to ROW to avoid issues with
    # replicate_do_db
    binlog_format=ROW
Run Code Online (Sandbox Code Playgroud)

000-replication-slave.sql

-- configure the connection to the master
--
CHANGE MASTER TO
    MASTER_HOST='database',
    MASTER_USER='replicant',
    MASTER_PASSWORD='password',
    MASTER_PORT=3306,
    MASTER_USE_GTID=slave_pos,
    MASTER_CONNECT_RETRY=10;

-- start the slave
--
START SLAVE;
Run Code Online (Sandbox Code Playgroud)

replication.cnf 对于奴隶:

[mariadb]
    server_id=1000
    relay-log = /var/log/mysql/mysql-relay-bin.log
    log_bin = /var/log/mysql/mysql-bin.log
Run Code Online (Sandbox Code Playgroud)

我在从站上看到的错误是这样的:

Could not execute Write_rows_v1 event on table mysql.user; Duplicate entry 'localhost-root' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; 
Run Code Online (Sandbox Code Playgroud)

问题与此问题类似,但我正在尝试使用库存的 MariaDB 映像(而不是自定义 Docker 映像)。

我尝试了许多不同的事情:

  1. replicate_do_db = mydatabase在从站上设置它并且它确实有效,但考虑到从站过滤的问题,我不想使用它。我认为它设置正确,但我宁愿不冒险。

  2. 我已经尝试从mysql.user表中删除有问题的行(都带有DELETE语句,当没有时,带有TRUNCATE)在CHANGE MASTER语句之前的奴隶上,但这不起作用。

我应该提到我已经搜索了这个问题的答案,但是所有在线教程都建议在主服务器上获取二进制日志位置并在开始复制之前手动更新从属位置。我正在寻找一种解决方案,它可以让我在创建主站后立即设置从站并从头开始同步。

所以,简而言之,问题是如何设置主从来复制所有内容,从在主从上全新安装 MariaDB 开始?

Kry*_*ten 2

我已经为此找到了一个答案 - 这看起来有点像黑客,但它似乎有效。

回顾一下:目标是使用 MariaDB 10.3.4(在 Docker 容器中,尽管这不一定是必需的)从头开始(即新安装的空数据库)设置一个具有单个从属的主服务器,以便系统将简单地启动并工作,不会出现任何错误。我想使用 MariaDB 的全局事务 ID。

我遇到的问题是一些查询失败,因为用户已经存在于数据库中(已作为 Docker 容器初始化的一部分进行设置)。当主服务器发送创建这些用户的查询时,从服务器失败,因为这些行已经存在于表中mysql.users

解决方案是在执行该CHANGE MASTER语句之前简单地删除这些用户。这是从站启动时运行的 SQL:

-- drop the application user
DROP USER IF EXISTS 'myuser'@'%';
-- drop the root user
DROP USER IF EXISTS 'root'@'localhost';

CHANGE MASTER TO
    MASTER_HOST='database',
    MASTER_USER='replicant',
    MASTER_PASSWORD='password',
    MASTER_PORT=3306,
    MASTER_USE_GTID=slave_pos,
    MASTER_CONNECT_RETRY=10;
Run Code Online (Sandbox Code Playgroud)

反复试验表明,这两个用户是失败的。

此配置带来的一个问题是:一旦从属设备完成其初始同步,您就无法再以root@localhost. 对此有几种解决方案:

  1. 登录为root@slave_hostname,或
  2. 创建一个新用户,该用户对于具有 root 权限的从站来说是唯一的。