关于'mysql主从自动容器化'的错误集合
veriosn: "3.8"
- 原因
docker-compose的version字段必须为int类型而不能是string - 解决
删除双引号
2.使用同一存储路径导致InnoDB无法使用表文件
挂载不同的数据卷
3.无法非交互式使用密码
-p与'密码'之间不可以有空格,如果有空格就会导致必须交互式输入密码,其他非-p的参数没有这种限制
- 解决
删除-p与'密码'之间的空格
4.MASTER状态表为空
- 错误
- 原因
没有开启二进制日志,只要开启二进制日志,就会看见二进制日志状态
- 解决
修改配置文件
至少添加log_bin=mysql-bin.log开启二进制日志,其他可以默认
5.多单词赋值变量错误
- 错误
- 原因
一般值是一个完整的内容,不需要添加内容,一旦值是由多个单词组成,中间有空格,必须使用引号括起来,否则只能赋值第一个单词,后面会直接报错
- 解决
加引号
6.bin_log的断点引号问题
- 错误
- 原因
bin_log的断点master_log_pos不可以加引号,它是int型的
- 解决
删除引号
7.函数使用错误
- 错误
if [ ${ROLE} -eq "master" ]; then
MASTER()
#角色为slave
elif [ ${ROLE} -eq "slave" ]; then
SLAVE()
else
echo "没有指定角色或角色错误" >>/dev/stderr
fi- 原因
以上脚本有两个问题
错误的使用函数MASTER,正确的使用应该为MASTER而不是MASTER()
错误的使用-eq,这是用于整数比较的,无法用于字符串判断,应该使用=,需要注意,普通的[]是不支持==的,[[]]支持==
- 解决
使用=进行字符串判断
删除使用函数后的括号
8.mysql的-e参数分隔问题
- 错误
mysql -u 'root' -p"${MYSQL_ROOT_PASSWORD}" -e "${CREATE_SQL}" "${GRANT_SQL}" "${FLUSH_SQL}"会报错登录失败
- 原因
因为-e后面只能跟一个值,这里直接根了3个值导致错误
- 解决
连续使用3个mysql+'-e'完成3个操作
或直接使用引号将3个操作都括起来
9.SLQ重复创建错误
- 错误
- 原因
由于已经传入MYSQL_USER与MYSQL_PASSWORD给容器了,mysql自动创建了用户
已经存在slave用户了,无法再创建
- 解决
不要创建或删除再创建
10.slave无法连接master
- 错误
- 原因
虽然设置了depends_on,但是它不保证服务完全启动,仅保证启动顺序,这就导致虽然master容器启动了,但是其中的mysql服务没有开启,但同时slave已经开启请求master节点的数据了!
- 解决
强制slave节点后启动
使用sleep或者使用depends_on的condition设置服务必选完全启动
sleep有些粗糙,没有验证master节点是否已经启动,可写一个循环连接master的脚本直至达到N次停止或连接上,然后开始初始化,
补:现可以结合dockercompose的depends_on和healthcheck强制要求必须先完成master的启动
11.docker-compose修改前未down问题
- 错误
脚本内容为:,停止docker-compose-->删除数据卷-->启动docker-compose
- 原因
刚刚我修改了docker-compose却没有停止旧的docker-compose导致原本'停止docker-compose'无法停止旧的docker-compose启动的容器,因此无法删除正在使用中的数据卷
- 解决
手动停止容器并删除
修改docker-compose之前需要先停止它启动的容器
12.depends_on错误指定容器名
- 错误
- 原因
depends_on需要指定服务名而不是容器名
- 解决
修改容器名为服务名
13.变量引用顺序问题
- 错误
CHANGE_MASTER_SQL="....master_log_file=${FILE},master_log_pos=${POSITION};"
FILE="$(xxx)"
POSITION="$(xxx)" - 原因
可以发现,FIEL与POSITION的定义在CHANGE_MASTER_SQL后,这就导致CHANGE_MASTER_SQL在使用FIEL与POSITION时他们还没定义,就为空导致错误
- 解决
更换位置,将FILE与POSITION的位置更换到上面
新发现
1.关于引用变量加单引号的问题
关于单引号如何加在引用变量上,我思考了很久,有常常一大段笔记描述的思考过程,测出好几个可用的方式然后,我发现原来在双引号中的单引号不会对中间的内容进行转义,那好,那么白想了,就是这么简单"echo '${NAME}'"
此方法用于为授权密码添加单引号
2.docker-compose的depends_on配置
depends_on普通版
depends_on:
- <service_A>depends_on升级版
depends_on
- restart: true(默认)/false 是否在更新被依赖容器后重启被依赖容器
condition:
- service_started 只保证容器启动顺序(默认)
- service_healthy 结合被依赖容器的healthcheck,需要完成健康检查才能启动依赖容器
- service_completed_successfully 被依赖容器服务启动才启动依赖容器,保证服务启动顺序
- required: true(默认)/false 是否在被依赖容器未启动的情况下阻止依赖容器的启动
3.关于*是否被shell翻译替换的问题
关于这个问题的解决,我花了至少2h,原因是我一直发现*.*在shell环境中被翻译为xxx.xxx形式的文件,并且mysql不允许在*.*两边加上任何引号,原本想试试能不能不翻译,但是如果不翻译echo出来就必须带引号(加上\转义也不行),问题似乎无解了,但是峰回路转,我发现mysql不会翻译*.*,这是为什么?

*.*两边加上任何引号" title="mysql不允许在*.*两边加上任何引号">

原来,只要在${变量}两边加上双引号就不会进行二次翻译
但是为什么呢?这需要用shell对变量的展开解释
- 如果通配符出现在没有引号包围的字符串中时,Bash 会在尝试执行命令之前对它们进行展开,这表示会匹配通配符
- 如果通配符被单引号包围,Bash不会对它们进行展开,但是其他变量同样不会翻译,直接输出
- 如果通配符被双引号包围,Bash会翻译变量,但是无视通配符,即仅翻译变量

仔细一看,这是刚学bash脚本时候学的单引号,双引号,反引号等等,没想到到现在给我造成如此大的困扰,果然,细节决定成败,换句话说,细节真的很难找!









