依刻学习 - mysql
type: channel
link: https://www.ykey.top/index.php/category/mysql/
description: mysql数据库
items: 使用xtrabackup实现mysql自动备份
items: MHA实践(4)
items: MHA实践(3)
items: MHA实践(2)
items: MHA实践(1)
items: mysql一键启动脚本(3)
items: mysql复习笔记(已废弃)
items: mysql双主双从+nginx容器自动化部署
items: mysql主从自动容器化(2) 错误
items: mysql主从自动容器化(1) 部署

使用xtrabackup实现mysql自动备份
type: item
date: 2025-09-04T04:44:00+08:00
description: 前言前两天看见网上有人抱怨mysql备份有点麻烦，所以我这两天写了个自动化备份mysql的脚本脚本#!/usr/bin/bash StepShow () { #tipEcho 第几步 主题 echo -e "\n------------------------------------------" echo -e "\033[34;3mstep $1 : $2\033[0m" echo -e "------------------------------------------\n" } WarnShow () { echo -e "\n\033[33;3m Warn: $1 \033[0m" } ErrorShow () { echo -e "\n\033[31;43;4m ERROR: $1 \033[0m" } TipShow () { echo -e "\n\033[32;3m TIP: $1 \033[0m" } TestMysqlRunnung () { systemctl start mysqld &> /dev/null # 测试mysql是否运行 if [ $( ps -aux|grep 'mysqld '|wc -l) -gt 1 ]; then # 进一步检查 mysql -u backup -p"${password}" -e "SELECT 1" &>/dev/null if [ $? -eq 0 ];then echo 'mysql正在运行' else echo -e '\033[31m mysql没有运行 \033[0m' fi else echo -e '\033[31m mysql没有运行 \033[0m' fi } TestXtrabackupExist () { # 测试是否安装Xtrabackup xtrabackup --version &>/dev/null if [ $? -eq 0 ]; then echo 'xtrabackup已安装' else echo 'xtrabackup未安装' exit 2 fi } CheckBackupDir () { # 创建备份目录 echo '注意会清除目录内同名文件' if [ ! -d "${backupDir}" ];then rm ${backupDir} -f mkdir ${backupDir} fi } ChooseStrategy(){ # 创建策略文件用于永久存储策略 if [ $(ls ${backupDir}|grep strategy|wc -l) -ne 1 ];then touch ${backupDir}/strategy fi # 在strategy为空时才进行策略选择，否则会直接读取 while [ $(cat ${backupDir}/strategy|wc -l) -eq 0 ];do echo -e "1.增量备份\n2.差异备份" read -p '选择:' choose if [ ${choose} -eq 1 ];then echo -e 'increment\n###' > ${backupDir}/strategy elif [ ${choose} -eq 2 ];then echo -e 'difference\n###' > ${backupDir}/strategy else echo '错误输入，重新输入' fi done echo '创建成功' } CheckLatest(){ latestBackup=$(cat ${backupDir}/strategy|tail -1) if [ ${latestBackup} == '###' ];then status=1 # 需要全量备份，status为1 echo '没有备份，即将完整备份' else # 已经全量备份就要进行差异或增量备份 strategy=$(cat ${backupDir}/strategy|head -1) [ ${strategy} == 'difference' ] && status=2 # 差异备份 [ ${strategy} == 'increment' ] && status=3 # 增量备份 echo "最新的备份为${latestBackup}" fi } Backup() { oldtarget=${latestBackup} # oldtarget--inc3 newtarget--inc4 # 初始化newtarget if [ ${oldtarget} == '###' ];then newtarget='base' elif [ ${oldtarget} == 'base' ];the…

MHA实践(4)
type: item
date: 2025-03-24T00:46:00+08:00
description: 前言复习MHA,通过两种方式实现MAH的VIP漂移|NODE|IP|ROLE||-|-|-||T1|192.168.179.191|master,MHA-node||T2|192.168.179.192|slave,MHA-manager,binlog-server||T3|192.168.179.193|slave,MHA-node|配置了binlog-server,减轻主库压力,保持日志的长时间保持(用于主从切换后复制)MHA自带脚本方式这个自带脚本需要下载tgz包查看,位于mha4mysql-manager-0.58/samples/scripts,rpm包(yum安装)没有脚本模板请先完成mysql一主二从的搭建,完成mha-manage与node的安装1.添加故障切换脚本vim /app/tools/masterha/app1.cnf #故障切换VIP脚本 master_ip_failover_script= /app/tools/masterha/master_ip_failover #在线切换VIP脚本 master_ip_online_change_script= /app/tools/masterha/master_ip_online_changeMHA提供了故障切换脚本模板master_ip_failover2.修改脚本修改master_ip_failovercp /app/tools/masterha/app1/master_ip_failover.pl \ /app/tools/masterha/app1/master_ip_failovervim /app/tools/masterha/master_ip_failover #!/usr/bin/env perl use strict; use warnings FATAL => 'all'; use Getopt::Long; my ( $command, $ssh_user, $orig_master_host, $orig_master_ip, $orig_master_port, $new_master_host, $new_master_ip, $new_master_port ); #添加或修改如下内容 #指定VIP my $vip = '192.168.179.200/24'; my $key = '0'; #这里可能需要修改网卡 my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down"; GetOptions( 'command=s' => \$command, 'ssh_user=s' => \$ssh_user, 'orig_master_host=s' => \$orig_master_host, 'orig_master_ip=s' => \$orig_master_ip, 'orig_master_port=i' => \$orig_master_port, 'new_master_host=s' => \$new_master_host, 'new_master_ip=s' => \$new_master_ip, 'new_master_port=i' => \$new_master_port, ); exit &main(); sub main { print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n"; if ( $command eq "stop" || $command eq "stopssh" ) { my $exit_code = 1; eval { print "Disabling the VIP on old master: $orig_master_host \n"; &stop_vip(); $exit_code = 0; }; if ($@) { warn "Got Error: $@\n"; exit $exit_code; } exit $exit_code; } elsif ( $command eq "start" ) { my $exit_code = 10; eval { print "Enabling the VIP - $vip on the new master - $new_master_host \n"; &start_vip(); $exit_code = 0; }; if ($@) { warn $@; exit $exit_code; } exit…

MHA实践(3)
type: item
date: 2025-03-23T11:31:00+08:00
description: 前言复习MHA,搭建binlog-server并测试|NODE|IP|ROLE||-|-|-||T1|192.168.179.191|master,MHA-node||T2|192.168.179.192|slave,MHA-manager,binlog-server||T3|192.168.179.193|slave,MHA-node|配置了binlog-server,减轻主库压力,保持日志的长时间保持(用于主从切换后复制)实践在某节点创建存放binlog的目录(最好是mysql从节点上,否则可能有问题,未验证)#mysql从节点192.168.179.192 mkdir -p /app/data/mysqlbinlog远程备份binlog#指定备份binlog的目标master节点(一般就直接从mysql-bin.000001开始复制) nohup mysqlbinlog --no-defaults --read-from-remote-server --raw --result-file=/app/data/mysqlbinlog/ --host=192.168.179.191 --port=3306 --user=monmha --password='!@#$%^&[]{O2p' --stop-never mysql-bin.000001 --server-id=9999 &>/dev/null & #--read-from-remote-server：从远程服务器直接读取binlog #--raw：输出原始binlog内容 #--result-file：指定输出目录(不是文件名) #经测试,--result-file准确说是文件名前缀(如/data/backcp-->backcpmysql-bin.000001)或者是路径,一定要在末尾加/(如/data/backcp/-->backcp/mysql-bin.000001) #--stop-never:，表示持续监听新事件要在--result-file指定的目录后加/,不可以使用任何文件名,因为MHA只能识别mysql-bin.000001类型的binlog文件,其他的文件名(例如backcpmysql-bin.000001)不认修改mha配置文件#由于本次将一个slave设置为binlog server,在其server中添加以下参数防止其变为master,防止该节点成为master增加宕机概率,导致mha无法获取备份的binlog no_master=1 #在最后添加 [binlog1] hostname=192.168.179.192 master_binlog_dir=/app/data/mysqlbinlog检验#masterha_check_repl会检查 masterha_check_repl --conf=/app/tools/masterha/app1.cnf 启动mhanohup masterha_manager --conf=/app/tools/masterha/app1.cnf &>/app/tools/masterha/app1/manager.log &测试1.关闭从节点IO线程stop slave io_thread; show slave status\G;2.主节点写并更新binlog#主节点写操作,使用flush logs;快速更新日志 create database test; use test; flush logs; create table dept ( deptno int unsigned auto_increment primary key comment '部门编号', dname varchar(15) comment '部门名称' , loc varchar(50) comment '部门所在位置' )engine = innodb default charset=utf8mb4 comment='员工部门表'; flush logs; insert into dept values (10,'ACCOUNTING','NEW YORK'); flush logs; insert into dept values (20,'RESEARCH','DALLAS'); flush logs; insert into dept values (30,'SALES','CHICAGO'); flush logs; insert into dept values (40,'OPERATIONS','BOSTON'); flush logs; show master status\G; 此时slave节点没有变化,因为关闭…

MHA实践(2)
type: item
date: 2025-03-23T01:04:00+08:00
description: 前言复习MHA,练习MHA工具,包括测试,master在线切换主机,master离线切换主机|NODE|IP|ROLE||-|-|-||T1|192.168.179.191|master,MHA-node||T2|192.168.179.192|slave,MHA-manager||T3|192.168.179.193|slave,MHA-node|MHA测试工具检查 MySQL 复制状况 一般在启动MHA之前检查masterha_check_repl --conf=/app/tools/masterha/app1.cnf 检查 MHA 的 SSH 配置状况masterha_check_ssh --conf=/app/tools/masterha/app1.cnf检测当前 MHA 运行状态masterha_check_status --conf=/app/tools/masterha/app1.cnfMHA自动转移(主从切换)流程MHA检查到master节点宕机MHA检查配置文件MHA关闭master节点以防万一新主节点的恢复此步包括选择从slave中按数据最接近master的原则选择新的master(如果某slave配置了candidate_master=1,则必为主节点)新slave节点change master到新的master,然后进行数据差异检查,对齐可以发现其中并没有配置任何用户,还是使用app1.cnf中的配置文件,所以使用的复制账号与监控账户跟之前是一样的,所以才需要在每个节点上(包括slave)都进行相同账号的创建和授权如果旧主重启,默认情况下MHA不会自动将其重新加入集群,也就是说可能需要手动切换,或者通过MHA故障切换脚本(这个脚本要自己写)MHA手动切换手动切换的前提时MHA没有启动,否则会触发自动转移检查MHA状态masterha_check_status --conf=<file>检查MHA监控与配置masterha_check_repl --conf=<file>手动切换masterha_master_switch --master_state=dead --conf=/app/tools/masterha/app1.cnf --dead_master_host=192.168.179.191 --dead_master_port=3306 --new_master_host=192.168.179.192 --new_master_port=3306 --ignore_last_failover #dead_master_host请参考配置文件,只能写配置文件中有的host(必须与配置相同,配置中是IP那么就不能写主机名)MHA在线切换:up:在线切换指的是master与slave都正常工作时进行配置恢复检查MHA状态masterha_check_status --conf=<file>检查MHA监控与配置masterha_check_repl --conf=<file>查看参数#查看Seconds_Behind_Master(从服务器当前与主服务器之间的数据同步滞后时间s) #slave节点 show slave status\G; #查看TIME #master节点 show processlist;在线切换主库masterha_master_switch --master_state=alive --conf=/app/tools/masterha/app1.cnf --new_master_host=192.168.179.193 --orig_master_is_new_slave --running_updates_limit=1000 --interactive=0 #--orig_master_is_new_slave 将原master变成新slave #Seconds_Behind_Master值必须小于--running_updates_limit指定的值 #TIME(show processlist;中的TIME最大值)必须小于--running_updates_limit指定的值切换成功

MHA实践(1)
type: item
date: 2025-03-22T23:01:00+08:00
description: 前言复习mysql,搭建MHA架构,并且对MHA架构进行一定测试,标注出一些关键问题|NODE|IP|ROLE||-|-|-||T1|192.168.179.191|master,MHA-node||T2|192.168.179.192|slave,MHA-manager||T3|192.168.179.193|slave,MHA-node|可以将MHA-manager移至一个比较安全的节点,但是slave本身也可以(会配置no_master禁止T2成为master)实践1.配置域名解析cat >> /etc/hosts <<EOF 192.168.179.191 T1 192.168.179.192 T2 192.168.179.193 T3 EOF2.安装3台mysql请参考mysql一键启动脚本3.设置每个节点间的免密登录(每个节点都需要)ssh-keygen for i in 191 192 193;do ssh-copy-id root@192.168.179.$i;done4.配置用户(推荐所有节点,只有主节点也行)所有节点都需要授权是因为主从可能切换,此时原来的从节点就成为主节点,那么同时也需要复制账户但是实际上只需要主节点就行了,因为并没有配置忽略mysql这个database(user表在其中),所以从节点复制时也会复制授权语句#监控用户monmha,监控数据库变化 grant all privileges on *.* to 'monmha'@'T1' identified by '!@#$%^&[]{O2p'; grant all privileges on *.* to 'monmha'@'T2' identified by '!@#$%^&[]{O2p'; grant all privileges on *.* to 'monmha'@'T3' identified by '!@#$%^&[]{O2p'; grant all privileges on *.* to 'monmha'@'192.168.179.*' identified by '!@#$%^&[]{O2p'; #复制用户mha,用于复制数据库 grant REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'mha'@'192.168.179.*' identified by '1U@1UK6$1UK6%5n5*}\9M1UK69M5n5n'; grant REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'mha'@'T1' identified by '1U@1UK6$1UK6%5n5*}\9M1UK69M5n5n'; grant REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'mha'@'T2' identified by '1U@1UK6$1UK6%5n5*}\9M1UK69M5n5n'; grant REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'mha'@'T3' identified by '1U@1UK6$1UK6%5n5*}\9M1UK69M5n5n'; flush privileges; #192.168.179.*与192.168.179.%基本相同 #在mysql8.0中,创建用户与授权需要分开来,也就是需要两步 #mysql需要对指定NDS进行解析,即使5.修改配置文件vim /etc/my.cnf [mysqld] # ===== 基础配置 ===== # 唯一ID（主从必须不同，如主=1，从=2） server-id = 1 datadir = /var/lib/mysql socket = /var/lib/mysql/mysql.sock log-error = /var/log/mysqld.log pid-file = /var/run/mysqld/mysqld.pid # ===== 二进制日志配置 ===== # 所有节点均需配置（MHA要求） log-bin = /var/lib/mysql/mysql-bin binlog_format = ROW expire_logs_days = 7 max_binlog_size = 100M # 主库建议1，从库可设0 sync_binlog = 1 # ===== 中继日志配置 ===== # 所有节点均需配置（MHA要求） relay_log = /var/lib/mysql/relay-bin # 控制sql线程定时清理中继日志 relay_log_p…

mysql一键启动脚本(3)
type: item
date: 2025-03-20T22:17:00+08:00
description: 前言最近在搭建,经过一段时间,对shell有了更深入的了解,解决了原来的mysql登录问题,并且添加了比较简单的密码复杂性检查脚本#/bin/bash #version: v3 #author: YK #update: 安装完毕直接登录,对密码进行检查 #网络测试 ping -c2 223.109.81.112 &>/dev/null #百度IP if [ $? -ne 0 ]; then #$?代表上一个命令执行结果,0为正确 echo "网络不通"; exit 0; else ping -c2 www.baidu.com &>/dev/null if [ $? -ne 0 ]; then echo "DNS有问题"; exit 0; fi fi #实现有颜色的警告(前景色:31红,32绿,33黄,34蓝,背景色:41红....44蓝) echo -e "\033[31m 本脚本会对之前的mysql进行删库,谨慎执行\033[0m" #存放路径 echo -e "mysql的rpm包存放路径(默认为/usr/local/mysql):\n注意,会清空该目录" read rpm_where locate=${rpm_locate:-"/usr/local/mysql"} if [ ! -d ${locate} ]; then #-d 匹配目录是否存在,存在时为true,使用!可以取反 mkdir -p ${locate} fi rm ${locate}/mysql-* -f groupadd mysql &>/dev/null useradd -r -g mysql mysql &>/dev/null chown -R mysql:mysql /usr/local/mysql chmod -R 755 /usr/local/mysql #安装版本 echo -e "安装mysql5.7?\nyes-->5.7\nno -->8.4 " #使用 -e才能解释转义字符,否则类型\n都不会解释 while true; do read -p "请输入 (默认为yes): " version version=${version:-"yes"} case ${version} in [Yy][Ee][Ss]) #注意选项末尾有个')' #此方法无视大小写且简单易实现 is_mysql57=$(ls ${locate}|grep mysql-5.7.44-1.el7.x86_64.rpm-bundle.tar|wc -l ) if [ ${is_mysql57} -eq 0 ]; then echo "正在下载mysql5.7" wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.44-1.el7.x86_64.rpm-bundle.tar -P ${locate} &>/devnull fi echo "已经下载mysql5.7" break #此break是对于外循环while的,case本身不需要break ;; [Nn][Oo]) is_mysql84=$(ls ${locate}|grep mysql-8.4|grep el7.x86_64.rpm-bundle.tar|wc -l ) if [ ${is_mysql84} -eq 0 ]; then echo "正在下载mysql8.4" wget https://dev.mysql.com/get/Downloads/MySQL-8.4/mysql-8.4.4-1.el7.x86_64.rpm-bundle.tar -P ${locate} &>/dev/null #wget的-P可以指定下载的位置 fi echo "已经下载mysql8.4 " break ;; *) echo "请输入yes/no,或使用'ctrl+c'退出" ;; esac done echo "下载完成" echo "mysql密码(默认密码为MyStr0ngP@ssw0rd!):" read secret_n secret_new=${secret_n:-"MyStr0ngP@ssw0rd!"} echo "mysql密码:$secret_new" #密码验证 check_passwd ${secret_new} if [ $? -eq 1 ]; then echo "退出安装" exit 1 elif [ $? -eq 0 ]; then echo "继续安装" fi echo "正在删除旧安装包" rpm -qa|grep mysql* |xargs yum remove -y >&/dev/null rpm -qa|…

mysql复习笔记(已废弃)
type: item
date: 2025-03-06T21:24:00+08:00
description: 发现有一些错误,本文已经废弃数据库SQL操作SQL动词DDL数据定义(defind)CREATE,DROP,ALTERDQL数据查询(query)SELECTDML数据操纵(manage)INSERT,UPDATE,DELETEDCL数据控制(contronl)GRANT,REVOKEDDL 数据定义1.库的基本操作1.创建库 create database db1 [if not exists db1]; #判断库是否存在，不存在则创建 2.查看所有数据库(可在任意库中使用) show databases; 3.修改数据库字符信息 alter database db1 character set utf8; 4.删除数据库 drop database db1; 5.进入库(可在任意库中使用) use db1;2.表的基本操作1.创建表 create table student( id int AUTO_INCREMENT NOT NULL, name varchar(32) DEFAULT '小王子', age int NOT NULL, score double(4), birthday date UNIQUE, insert_time timestamp Sex CHAR(1) CHECK (Sex IN ('M', 'F')), PRIMARY KEY (id), FOREIGN KEY (birthday_time) REFERENCES Persons(birthday_time) ); #字段类型,名称,长度,约束 2.修改表 ALTER TABLE <表> ADD COLUMN <新列名> <数据类型> #加列 ADD CONSTRAINT <完整性约束名> 约束 #加约束 DROP COLUMN <列名>[CASCADE|RESTRICT] #删列 DROP CONSTRAINT <完整性约束名> [CASCADE|RESTRICT] #删约束 RENAME COLUMN <列名> TO <新列名> #重命名 ALTER COLUMN <列名> TYPE <数据类型> #改类型 3.删除表 DROP TABLE 表名［RESTRICT| CASCADE］； RESTRICT：限制(保守)。 如果存在依赖该表的对象，则此表不能被删除 CASCADE：没有限制(连坐)。 在删除基本表的同时，相关的依赖对象一起删除 4.建立索引 CREATE [UNIQUE] [CLUSTER] INDEX <索引名> ON <表名>(<列名>[<次序>]…)； 索引可以建立在多列上，升序：ASC，降序：DESC。默认ASC UNIQUE表明此索引的每一个索引值只对应唯一的数据记录 CLUSTER表示要建立的索引是聚簇索引 create unique index A on SC(SNO); 一张表只能创建一个聚簇索引。约束类型 AUTO_INCREMENT #自增,只能是数字,必加NOT NULL且一般作为Pkey DEFAULT "xxx" #默认值,当没有插入该列时,默认 UNIQUE #唯一 NOT NULL #非空即不是NULL CHECK(条件) #检查,可追加在col后面,但这样条件必须只能由col,也可单独成行 #int col CHECK(col IN ('x1','x2'...)), #追加 #CHECK(col1 > 2 AND col2 <100), #单独成行 #条件可以是 IN选择,<>大小,支持AND,OR,不支持通配符 PRIMARY KEY (col) #设为主键,唯一非空,可追加在col后面也可单独成行 FOREIGN KEY (col1) REFERENCES tb(col2) #外键,将tb表的col2作为本表col1上的外键,插入的值必须是col2上存在的 相同不同UNIQUE唯一性可以为NULL(仅一个)一个表可有多个PRIMARY KEY唯一性不可为NULL一个表只能有一个表内元素的数据类型与约束 数字 int,smallint,bigint #范围有差别 小数 numeric(p,d) 精度p,小数点后有d位(数字总数可以小于p,但d位小数必须有) #等价于decimal(p,d) dec(p,d) 精度 float(p,d)<double(p,d)<dec(p,d) #虽然指定了精度与小数位,但实际存储还是因为位数有误差 时间 年月日 date 年月日时分秒 datetime 时区时间timestamp #适用于经常插入或更新 时分秒 time 年份 year 字符串 固定长度的字符串 char(n) 占用n字符 可变长度的字符串 varchar(n) 占用实际字符+一部分存储长度 …

mysql双主双从+nginx容器自动化部署
type: item
date: 2025-02-28T19:28:00+08:00
description: 前言本博客基于之前的mysql单主单从容器自动化搭建。架构图补:这里使用nginx不是最优选择,nginx只能通过UDP简单轮询实现mysql的负载均衡,应该使用MySQL Router或ProxySQL实现相较于单主单从节点,双主双从自动化的难点大多数都相同,但是又有新的问题。1.双主的启动顺序问题?因为两个master都要互相change master,这就需要另一个master已经启动,这就会产生冲突,个人想法是先启动master1服务,但是在change master前添加阻塞(sleep或远程连接master2),先让master2完成''启动+change master'',然后再继续master1的change master。具体请参考<启动策略>2.master的ROLE问题?初始化脚本init.sh是按照角色来划分SQL的使用,但是双主的master既做master又做slave,所以我添加了新角色m_s,并且优化了脚本的构成,使用更多的函数,方便理解。3.nginx的负载均衡?用nginx的upstream模块实现mysql集群的负载均衡。启动策略一般情况(即主机安装),mysql集群的启动比较随意,因为手动输入可以控制何时执行命令,大致流程如下1.master1启动,授权2.master2启动,授权3.master1完成复制4.master2完成复制5.slave1启动,复制6.salve2启动,复制相较于单主单从,双主双从更加复杂,如果不加以限制同时启动master1与master2使其同时执行毫无疑问是错的,但是简单使master1先于master2服务启动仍是有问题的,关键就在于master1复制时要求master2已经完成启动并授权,反过来也是。如果只是先启动master1,master1已经到了复制,但是发现master2没有授权甚至没有启动,会直接报错,所以master1与master2的执行SQL顺序更加重要!1.没有限制启动的双主如果没有限制,在'复制'时可能由于另一个master没有启动或没有授权导致错误要求复制时另一个master必须启动且已经授权master执行流程相同(便于写脚本,非硬性要求)2.推导流程图关于双主启动策略这块,个人觉得是mysql双主双从自动化启动的核心问题1.master2的等待1:主要是为了保证master1优先启动,通过docker-compose的healthycheck实现(通过脚本测试master1是否启动也可行,但是不选用)2.master2的等待2:这里其实可以不等待,因为此时master1已经开始,没有实际意义,仅用于使master1于master2流程相同3.master1的等待:这个等待的用处是很大的,主要是通过脚本实现检查并等待master2启动完成+授权,然后再进行复制注意:为了保证init.sh的通用性,使的master1和master2的启动流程相同,我把流程不同的部分分到docker-compose中(没错,就是'等待1'),但实际上,可以选择使用多个init.sh分别启动master1和master2总结:''等待1'会写入docker-compose,作为master1的healthycheck''等待''与''等待2'会写入脚本,用于测试另一个master是否已经启动从节点只需要等待主节点启动即可nginx可以直接启动,不需要控制实操env是环境变量文件init.sh是容器初始化脚本my{1..4}.cnf分别是master1,master2,slave1,slave2的mysql配置文件nginx目录下的都是nginx的配置文件START是启动脚本1.docker-compose.ymlversion: "3.8" services: master1: image: mysql:5.7 container_name: mysql_master1 restart: always ports: - 3306 volumes: - data1:/var/lib/mysql - /app/docker/mysql_cluster/my1.cnf:/etc/mysql/conf.d/my.cnf - /app/docker/mysql_cluster/init.sh:/docker-entrypoint-initdb.d/init.sh networks: - mysql_cluster env_file: - env environment: - ROLE=m_s #双主的master也有担当slave的角色,所以需要传输MASTER - MASTER=mysql_master2 #command: healthcheck: tes…

mysql主从自动容器化(2) 错误
type: item
date: 2025-02-26T19:42:00+08:00
description: 关于'mysql主从自动容器化'的错误集合版本字符类型错误错误veriosn: "3.8"原因 docker-compose的version字段必须为int类型而不能是string解决删除双引号2.使用同一存储路径导致InnoDB无法使用表文件错误 原因 因为master与slave节点同时挂载了同一个数据卷到/var/lib/mysql上,这是mysql存储数据的地方,某些文件(例如表文件)已经被使用,无法被第二个服务使用解决挂载不同的数据卷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.关于引用变量加单引号的问题关于单引号如何加在引用变量上,我思考了很久,有常常一大段笔记描述的思考过程,测出好几…

mysql主从自动容器化(1) 部署
type: item
date: 2025-02-26T17:13:00+08:00
description: 环境服务版本centos7.9mysql5.7docker26.1.4docker-compose2.27.1使用docker-compose结合脚本进行自动化部署mysql一主一从主节点即master节点容器从节点即slave节点容器'双主双从'等待未来博客思路首先理清一般非容器化mysql主从部署思路:在多主机上安装mysql(统一版本)修改配置文件(区分master与slave)主节点需要创建复制用户并授权,进行测试从节点需要指定主节点并开启复制线程但是容器化就要有N个问题,主要集中在3,4点上如何保证主节点先于从节点开启?如何从主节点容器获取binlog的文件与断点?如何非交互的使用mysql?如何进行mysql初始化?解答:1.如何保证主节点先于从节点开启?这个问题如果单独使用dockerfile或直接docker启动其实没什么问题,只要先启动master容器就行了,但是如果使用docker-compose呢?我的第一个想法就是使用depends_on,salve容器依赖master容器不就行了吗?那就太easy,不会放这里了,确实可以使用depends_on设置优先级,但是docker-compose启动了容器不代表服务已经启动了!举个简单的例子,如果docker运行比较多就会发现有的容器刚启动还没ps就挂了,有的启动后需要等一会才挂掉,为什么不直接挂断?这是因为容器虽然启动了,但是服务还正在启动,然后发现启动不了,容器就挂了docker-compose这里也是一样,depends_on只能设置master优先启动,但此时服务可能正在启动,此时slave如果直接设置复制change master..会直接报错(经测试,即使设置了depends_on,master服务启动也比slave服务慢!)实际上需要的不是master容器先于slave容器启动,而是master的mysql服务先于slave的mysql服务启动,我想到的最简单的方法就是在slave的初始化脚本中使用sleep,这样就可以强制salve的mysql服务启动后于master的mysql服务启动补:仅使用depends不能保证服务完全启动,只能保证启动顺序,但是depends_on是可以设置需要被依赖容器完全启动才启动依赖容器2.如何从主节点获取binlog的文件名与断点并传入从节点?通过mysql的-h可以通过容器名实现跨节点的登录mysql,然后使用show master status结合三剑客过滤出FILE与POSTION字段,这样就可以直接在从节点直接获取binlog的文件名与断点3.如何非交互的使用mysql?通过mysql的-e参数可以实现非交互式的操作mysql,需要注意的是,如果需要连续输入多个命令可以使用双引号将SLQ扩起来,这样就不用使用多个mysql命令重复登录操作就可以一次实现操作了4.如何进行mysql初始化?使用mysql的初始化脚本,初始化脚本docker-entrypoint.sh会执行docker-entrypoint-initdb.d中的脚本,只要将脚本传入其中即可作为初始化脚本最终使用文件master的配置文件my1.cnfslave的配置文件my2.cnfdocker-compose.yml初始化脚本init.sh启动命令脚本START目录层级如下实现1.master的配置文件my1.cnf[mysqld] datadir=/var/lib/mysql symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid server_id=1 #开启binlog日志 log_bin=mysql-bin.log binlog_format=ROW max_binlog_size=500M expire_logs_days=7 slave_skip_errors=1062 log-slave-updates=1 auto-increment-increment=2 auto-increment-offset=1 replicate-ignore-db=mysql replicate-ignore-db=sys replicate-ignore-db=information_schema replicate-ignore-db=performance_schema 2.slave的配置文件my2.cnf[mysqld] datadir=/var/lib/mysql symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.p…