docke环境下.netcore 项目连接mysql一主一从服务器踩坑端口错误
主从复制的用途:
- 实时灾备,用于故障切换
- 读写分离,提供查询服务
主从部署必要条件:
- 主库开启binlog日志(设置log-bin参数)
- 主从server-id不同
- 从库服务器能连通主库
1、安装好docker
2、拉取好mysql相关镜像
3、在宿主机服务器上新建master以及master下3个目录,新建slave目录和slave目录下3个目录:


4、进入/home/mysqlcluster/1master1slave/master/conf目录中,vim my.cnf新建my.conf
vim my.cnf
将以下内容粘贴到my.conf中,执行:wq保存退出
[mysqld] server_id = 1 # 唯一标识,主库从库不能重复 log_bin = mysql-bin # 开启日志 binlog_format=STATEMENT # 日志记录的格式类型 # max_binlog_size = 512M # 单个日志文件最大 # expire_logs_day = 3 # 日志有效期(天) # binlog_do_db = test1,test2 # 日志记录(同步复制)那些数据库 # binlog_ignore_db = mysql,performance_schema,information_schema # 日志记录忽略那些数据库的

注:由于log_bin是个只读系统变量,不能动态的修改,只能再my.cnf里[mysqld]模块添加log-bin 配置,表示启用binlog,如果没有给定值,写成 log-bin=,则默认名称为主机名。(注:名称若带有小数点,则只取第一个小数点前的部分作为名称) log-bin的值决定了msyql 的binlog的名字,⽣成的binlog名字为mysql-bin.000001

其他master配置参考
[mysqld] ## 同一局域网内注意要唯一 server-id=1024 ## 开启二进制日志功能,可以随便取(关键) log-bin=mysql-bin secure_file_priv=/var/lib/mysql default_authentication_plugin=mysql_native_password #设置密码规则 max_connections=1000 #最大连接数设置 根据实际需要 自行调整
5、进入/home/mysqlcluster/1master1slave/slave/conf目录 vim my.cnf新建my.conf
vim my.cnf
将以下内容粘贴到my.conf中,执行:wq保存退出
[mysqld] server_id = 2 # 数据库唯一id,内网唯一 log_bin = mysql-bin # 开启日志,如果从库还会用做主库,建议配置 binlog_format=STATEMENT # 日志记录的格式类型 # max_binlog_size = 512M # 单个日志文件最大 # # expire_logs_day = 3 # 日志有效期(天) # # replicate_do_db = test1,test2 # 是在slave上配置,指定slave要复制哪个库 # # replicate-ignore-db=mysql,performance_schema,information_schema # 是在slave上配置,指定slave要忽略哪个库 # relay_log_recovery = 1 # 从库建议开启,有利于数据一致性 # log_slave_updates = 1 # 如果从库还会用做主库,建议开启
其他slave配置参考:
[mysqld] ## 设置server_id,注意要唯一 server-id=1022 ## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用 log-bin=mysql-slave-bin ## relay_log配置中继日志 relay_log=edu-mysql-relay-bin secure_file_priv=/var/lib/mysql default_authentication_plugin=mysql_native_password #设置密码规则 max_connections=1000 #最大连接数设置 根据实际需要 自行调整
6、执行下面命令新建master容器,并且映射宿主机三个目录为mysql的卷
docker run -d -p 3309:3306 --name mysql1master \ -v /home/mysqlcluster/1master1slave/master/data:/var/lib/mysql \ -v /home/mysqlcluster/1master1slave/master/conf:/etc/mysql/conf.d \ -v /home/mysqlcluster/1master1slave/master/log:/var/log/mysql \ -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.31
7、执行下面命令新建slave容器,并且映射宿主机三个目录为mysql的卷
docker run -d -p 3310:3306 --name mysql1slave \ -v /home/mysqlcluster/1master1slave/slave/data:/var/lib/mysql \ -v /home/mysqlcluster/1master1slave/slave/conf:/etc/mysql/conf.d \ -v /home/mysqlcluster/1master1slave/slave/log:/var/log/mysql \ -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.31
8、启动master和slave
![]()
9、启动完成后,使用navicat分别测试下远程连接master和slave,端口使用映射端口

10、进行slave账户创建及相关授权,slave账户是master上的一个账号,是在slave服务器上远程登录master服务器的账号,登录后用于主从复制操作
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
FLUSH PRIVILEGES;
11、 启动并且进入master容器,登录mysql
docker exec -it mysql1master /bin/bash
查看master状态
mysql> show master status;

或者执行:
show master status \G;

在另一个bash查看master的ip,配置slave 要用
docker inspect --format={{.NetworkSettings.IPAddress}} mysql1master
![]()
12、启动slave容器,并且登录slave的mysql
docker exec -it mysql1slave /bin/bash
bash-4.4# mysql -u root -p
Enter password:123456
13、如果刚才配置过slave,就先 停止slave,如果没配置过,跳过stop slave;
mysql> stop slave;

14、 配置slave
master_host使用刚才查询的ip,master_port使用master容器的端口,默认是3306 , master_log_file使用刚才master查询的值,master_log_pos使用刚才master查询的值,这两个值一定要跟master的一样
(此处绑定了错误的端口,导致后面Slave_IO_Running: Connecting)
mysql> change master to master_host='172.17.0.18', master_port=3309, master_user='slave',
master_password='123456',
master_log_file='mysql-bin.000006',
master_log_pos=3325;
master_port: Master的端口号,指的是容器的端口号,不是容器映射出阿里的端口,master的端口号为3306
master_user:用于数据同步的用户
master_password:用于同步的用户的密码
master_log_file:指定Slave从哪个日志文件开始复制数据,即上文中提到的File字段的值
master_log_pos:从哪个Position开始读,即上文中提到的Position字段的值
master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
15、 启动slave
mysql> start slave;
16、 查看salve数据库状态
mysql> show slave status \G;

17、 检查使用slave远程连接master
docker exec -it mysql1slave /bin/bash
bash-4.4# mysql -u slave -h 172.17.0.18 -p
Enter password:
show master status;

18、如果无法连接,需要重新授权slave用户 ,如果查看用户有slave用户,CREATE USER 'slave'@'%' IDENTIFIED BY '123456'; 这句就不用执行了
CREATE USER 'slave'@'%' IDENTIFIED BY '123456'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%'; FLUSH PRIVILEGES;
19、检查端口是否正确,发现绑定端口3309是错误,需要绑定容器原来的端口3306,
命令1:docker exec -it mysql1slave /bin/bash 命令2:mysql -u root -p #接着输入密码123456后回车 命令3:stop slave; 命令4:change master to master_host='172.17.0.18', master_port=3306, #注意此端口一定是master容器的端口,不是容器映射的端口,之前是使用了映射的3309端口是错误的 master_user='slave', master_password='123456', master_log_file='mysql-bin.000006', #注意这个要查询master的值,跟master的值一致 master_log_pos=2660;#注意这个要查询master的值,跟master的值一致 start slave;

20、验证主从复制成功,navicat在master中添加一条数据,过一会查看slave是否复制了数据


检验成功,主从复制搭建完毕!
21、 错误一:最终解决下图1报错是因为slave绑定的端口不对,slave要绑定master容器默认的3306端口而不是容器映射的3309 端口
图1 :解决错误前

图2:解决错误后

命令1:docker exec -it mysql1slave /bin/bash 命令2:mysql -u root -p #接着输入密码123456后回车 命令3:stop slave; 命令4:change master to master_host='172.17.0.18', master_port=3306, #注意此端口一定是master容器的端口,不是容器映射的端口,之前是使用了映射的3309端口是错误的 master_user='slave', master_password='123456', master_log_file='mysql-bin.000006', #注意这个要查询master的值,跟master的值一致 master_log_pos=2660;#注意这个要查询master的值,跟master的值一致
start slave;
22、master服务器日志报错:
2023-04-25T11:09:38.076294Z 13 [Warning] [MY-010908] [Server] Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. Statement: DELETE FROM `Test`.`Person` WHERE `Id` = 1 AND `Name` = '李四' AND `Age` = 20 LIMIT 1
解决方案 :修改binlog_format格式为mixed;需要先在 slave上,设置 binlog_format=mixed,之后再在master上设置
登陆mysql,如果slave还在运行any replication channel applier thread is running 需要先停止
mysql> STOP SLAVE SQL_THREAD;
mysql> set global binlog_format=MIXED;
mysql> START SLAVE SQL_THREAD;
slave截图

master截图

23、可能错误二 master 和slave的pos不一致

24 、可能错误三: master上新建slave账号无法从salve容器上登录master数据库
25、主从数据库容器都需要关闭防火墙,默认是关闭的

二、发布.net core 项目连接master数据库
2.1 使用以下命令生成宿主机/home/mysqltest/1master1slavecore/JwtToken目录下项目的镜像
docker build --no-cache -t 1master1slavecore -f Dockerfile .
2.2 使用以下命令运行容器镜像
docker run -it -d -p 8113:8113 --name 8113 1master1slavecore
2.3使用宿主机外网ip后导致报错

2.4、修改appsettings.json 将ip或者localhost改为*号 ,删除2.1和2.2生成的镜像和容器。然后重复2.1和2.2两个步骤重新生成镜像和容器

2.5、访问天气接口可以正常访问

2.6 访问person接口出现报错


2.7 使用--link命令将master容器和项目容器连接起来
docker run -it -d -p 8113:8113 --link mysql1master:mysql1master --name 8113 1master1slavecore
2.8 访问接口

2.9 查看日志

2.10 master数据库缺少persons表,新建persons表,并且添加1条数据,运行接口

2.11 运行addpersons接口,出现报错


2.12 将Id设置为主键,并且要勾选下面的自动递增,数据库的修改,对数据库表的修改无需重启docker容器

2.13 再次运行接口

2.14 docker部署的主从复制.netcore项目成功
2.15 隔了一段时间再次运行.netcore 程序时,需要先stop 然后再restart 项目容器,否则会出现连接数据库错误

浙公网安备 33010602011771号