我这两天正在跟着b站某docker教育视频学习,刚好讲到了mysql主从结构装备。我之前并没有装备这种结构的经历,对mysql的了解也不过是select句子的水平,所以装备起来适当挣扎,踩了不少坑。就跟咱们共享一下这次遇到的坑。

这儿主从数据库分别用mysql-master, mysql-slave命名。
首要发动mysql-master。3307是容器在宿主机的端口,3306是mysql在容器内部的端口。

$ docker run -p 3307:3306 --name mysql-master \
-v ~/docker/tmp/apps/mysql/mysql-master/log:/var/log/mysql \
-v ~/docker/tmp/apps/mysql/mysql-master/data:/var/lib/mysql \
-v ~/docker/tmp/apps/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql

很快这儿呈现了第一个坑。当我检查容器是否发动时,我发现容器发动失利了,检查过错信息如下。

mysqld: Can’t read dir of ‘/etc/mysql/conf.d/’ (OS errno 2 – No such file or directory)

过错信息很明晰,mysql没有找到 /etc/mysql/conf.d/这个装备文件。在docker中发动mysql时,为了数据耐久化,利用了卷(volume)这个概念。其间三个卷分别映射了日志,数据和装备。问题出在装备的目录。咱们有必要指定装备目录conf.d的方位。
更改如下成功发动mysql-master。

$ docker run -p 3307:3306 --name mysql-master \
-v ~/docker/tmp/apps/mysql/mysql-master/log:/var/log/mysql \
-v ~/docker/tmp/apps/mysql/mysql-master/data:/var/lib/mysql \
-v ~/docker/tmp/apps/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql

接着装备my.cnf。其间内容我都是抄的教程的,就不放在这儿了。

$ cd ~/docker/tmp/apps/mysql/mysql-master/conf
$ vim my.cnf 

然后为了使my.cnf收效,有必要重启mysql-master容器。重启后咱们进入该容器,而且测验运行sql句子,保证mysql正常作业。

$ docker restart mysql-master
$ docker exec -it mysql-master /bin/bash 
bash-4.4# mysql -p 
... 
mysql> show databases;
+--------------------+
| Database | 
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.04 sec)

mysql的确在运行,这样咱们就可以在主数据库上装备一个从(slave)用户了。
这儿’slave’@’%’是用户名和host,123456是暗码。

mysql> CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.07 sec)
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
Query OK, 0 rows affected (0.02 sec)

这样mysql-master主数据库就基本装备好了。现在开端从数据库mysql-slave的装备。

$ docker run -p 3308:3306 --name mysql-slave \
-v ~/docker/tmp/apps/mysql/mysql-slave/log:/var/log/mysql \
-v ~/docker/tmp/apps/mysql/mysql-slave/data:/var/lib/mysql \
-v ~/docker/tmp/apps/mysql/mysql-slave/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql

然后持续装备my.cnf并重启mysql-slave

$ cd ~/docker/tmp/apps/mysql/mysql-slave/conf
$ vim my.cnf
...
$ docker restart mysql-slave

现在大约应该装备从数据库了,不过咱们先进入主数据库,看一下主从状况。

$ docker exec -it mysql-master /bin/bash
bash-4.4# mysql -p
Enter password:
mysql> show master status;
+-----------------------+----------+--------------+------------------+-------------------+
| File                  | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------------+----------+--------------+------------------+-------------------+
| mall-mysql-bin.000001 |      711 |              | mysql            |                   |
+-----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql>

记住711这个数字,后面会用到。
现在进入从数据库mysql-slave而且进行主从装备。这儿master_host应该是宿主机的ip地址,用户名,暗码之前都提到过。master_port是主数据库mysql-master在主机上的端口。log file我不明白。log pos便是刚才说的711,检查主数据库的主从状况得到的。

$ docker exec -it mysql-slave bash
bash-4.4# mysql -p
Enter password:
...
mysql> change master to master_host='192.168.0.255',master_user='slave',master_password='123456',\
master_port=3307,master_log_file='mall-mysql-bin.000001',\
master_log_pos=711,master_connect_retry=30;
Query OK, 0 rows affected, 10 warnings (0.15 sec)

完成装备后测验发动slave而且检查他的状况。

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.05 sec)
\
mysql> show slave status \G;
*************************** 1. row ***************************
       Slave_IO_State: Connecting to source
         Master_Host: 192.168.0.255
         Master_User: slave
         Master_Port: 3307
        Connect_Retry: 30
       Master_Log_File: mall-mysql-bin.000001
     Read_Master_Log_Pos: 711
       Relay_Log_File: mall-mysql-relay-bin.000001
        Relay_Log_Pos: 4
    Relay_Master_Log_File: mall-mysql-bin.000001
      Slave_IO_Running: Connecting
      Slave_SQL_Running: Yes

这时假如主从数据库已经成功衔接,那么Slave_IO_Running和Slave_SQL_Running的状况都有必要是yes。这儿一直显现connecting,明显第二个坑呈现了。

error connecting to master ‘slave@192.168.0.255:3307’

我检查了状况里的Last_IO_Error,方法如下。

mysql> show slave status \G;
...
Last_IO_Error: error connecting to master 'slave@192.168.0.255:3307' - retry-time: 30 retries: 1 message: Can't connect to MySQL server on '192.168.0.255:3307' (111)

所以是衔接失利了,我当时就猜是不是主机ip或者端口搞错了。如下命令检查ip。

$ ifconfig | grep broadcast
	inet 192.168.0.95 netmask 0xffffff00 broadcast 192.168.0.255

所以我的主机ip地址是192.168.0.95!并不是192.168.0.255。
更改mysql-slave中的主数据库装备并重启slave。

mysql> change master to master_host='192.168.0.95',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000001',master
log_pos=711,master_connect_retry=30;
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.07 sec)
\
mysql> show slave status \G;
*************************** 1. row ***************************
      Slave_IO_Running: Connecting
      Slave_SQL_Running: Yes

Slave_IO_Running依然是connecting,还是没能成功发动。
好的,持续检查过错日志。

Last_IO_Error: Authentication plugin ‘caching_sha2_password’ reported error: Authentication requires secure connection

完好的过错信息如下。

Last_IO_Error: error connecting to master 'slave@192.168.0.95:3307' - retry-time: 30 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection

过错变了!好的变化啊。所以这一次是验证信息时出错了。似乎是要求secure connection。
我看到这个过错的时分一头雾水,超出常识范畴,只能去google搜索这个过错。成果还真让我找到了解决办法。
这时咱们要去主数据库,做一些slave用户信息的更改。注意,要去主数据库。

mysql> ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.02 sec)

这儿的用户名有必要是咱们之前创立的那个。
现在再去从数据库mysql-slave那边,再次测验发动slave。

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.10 sec)
mysql> show slave status \G;
*************************** 1. row ***************************
      Slave_IO_Running: Yes
      Slave_SQL_Running: No

这回Slave_IO_Running总算yes了,但是Slave_SQL_Running变成了no!!怎么回事?过错信息如下。

Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction ‘ANONYMOUS’ at master log mall-mysql-bin.000001, end_log_pos 994.

里面提到了log pos 994,我之前装备的分明是711。我猜是这儿出了问题,决议再次去检查主数据库的状况。

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

好吧真的变成994了,那么从数据库mysql-slave这边的设置也有必要跟着改。

mysql> change master to master_host='192.168.0.95',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000001',master_log_pos=994, master_connect_retry=30;
Query OK, 0 rows affected, 10 warnings (0.09 sec)
mysql> start slave;
            Slave_IO_Running: Yes
      Slave_SQL_Running: Yes

总算啊!!
下面验证一下主从结构建立成功。到主数据库里增加一个数据,看看能不能在从数据库那边查到。

mysql> create database db01;
Query OK, 1 row affected (0.04 sec)
mysql> use db01
Database changed
mysql> create table t1(id int, name varchar(20));
Query OK, 0 rows affected (0.10 sec)
mysql> insert into t1 values (10, 'scott');
Query OK, 1 row affected (0.03 sec)
mysql> select * from t1;
+------+-------+
| id  | name |
+------+-------+
|  10 | scott |
+------+-------+
1 row in set (0.00 sec)

最后到从数据库这边。

mysql> use db01;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from t1;
+------+-------+
| id  | name |
+------+-------+
|  10 | scott |
+------+-------+
1 row in set (0.00 sec)
mysql>

呈现了相同的数据!总算装备成功了!
总结一下便是英文有必要好。然后遇到过错不要慌,慢慢找原因。
中英文混合编辑文章好麻烦。