文章目录
一、MySQL的主从复制
主从复制原理
- 复制是MySQL的一项功能,允许服务器将更改从一个实例复制到另一个实例.
- 主服务器将所有数据和结构更改记录到二进制日志中.
- 从属服务器从主服务器请求该二进制日志并在本地应用其内容.
- IO线程:请求主库,获取上一次执行过程的新的事件,并存放到relaylog
- SQL线程:从relaylog中将sql语句翻译给从库执行
- 主从复制的前提
- 两台或两台以上的数据库实例
- 主库要开启二进制日志
- 主库要有复制用户
- 主库的server_id和从库不同
- 从库需要在开启复制功能前,要获取到主库之前的数据(主库备份,并且记录binlog当时位置)
- 从库在第一次开启主从复制时,必须获知主库:ip、port、user、password、logfile,pos
- 从库要开启相关线程:IO、SQL
- 从库需要记录复制相关用户信息,还应该记录到上次已经从主库请求到哪个二进制日志
- 从库请求过来的binlog,首先要存下来,并且执行binlog,执行过的信息保存下来
- 主从复制涉及到的文件和线程
- 主库
- 主库binlog:记录主库发生过的修改事件
- dump thread:给从库传送(TP)二进制日志线程
- 从库:
- relay-log(中继日志):存储所有主库TP过来的binlog事件
- master.info:存储复制用户信息,上次请求到主库binlog位置点
- IO thread:接收主库发来的binlog日志,也是从库请求主库的线程
- SQL thread:执行主库TP过来的日志
- 主库
- 原理
- 通过change master to 语句告诉从库主库的ip、port、password、file、pos
- 从库通过start slave命令开启复制必要的IO线程和SQL线程
- 从库通过IO线程拿着change master to 用户密码相关信息,连接主库,验证合法性
- 从库连接成功后,会根据binlog的pos问主库,有没有比这个更新的
- 主库接收到从库请求后,比较一下binlog信息,如果有就将最新数据通过dump线程给从库IO线程
- 从库通过IO线程接收到主库发来的binlog事件,存储到TCP/IP缓存中,并返回ACK更新master.info
- 将TCP/IP缓存中的内容存到relay-log中
- SQL线程读取relay-log.info,读取到上次已经执行过的relay-log位置点,继续执行后续的relay-log日志,执行完成后,更新relay-log.info

【实战】MySQL主从复制
将实例搭在两个机器上
- 主库操作
- 修改配置文件
vim /etc/my.cnf
[mysqld]
server_id=1
# 主库server-id为1,从库不等于1
log_bin=mysql-bin
# 开启binlog日志
- 导出一份全备数据给从库
mysqldump -uroot -p123456 -A -R -triggers --master-data=2 --single-transaction > /tmp/full.sql
scp /tmp/full.sql root@192.168.64.133:/tmp
- 创建主从复制用户
mysql -uroot -p123456
mysql> grant replication slave on *.* to slave@'192.168.64.%' identified by '123456';
# 创建slave用户
- 从库操作
- 修改配置文件导入全备数据
vim /etc/my.cnf
[mysqld]
server_id=5
# 主库server-id为1,从库不等于1
# 从库不需要开二进制日志
systemctl restart mysqld
mysql> source /tmp/full.sql;
mysql> show master status;
# 记录主库binlog及位置点,在主库上看,或者去全备日志里面grep -i ‘change master to’看
mysql -uroot -p123456
mysql> change master to
master_host='192.168.64.129',
master_user='slave',
master_password='123456',
master_log_file='mysql-bin.000001',
master_log_pos=120;
#master_auto_position=1; 自动找位点
mysql> start slave;
mysql> show slave status;
需要保证io线程和sql线程同时为yes才表示主从复制开启成功
如果是mysql装好之后直接克隆过来的,会出现uuid一致的情况
uuidgen命令生成uuid,替换掉原来文件中的uuid即可
主从复制基本故障处理
- IO线程报错
- user passoword ip port
- 网络:不同,延迟高,防火墙
- 没有跳过反向解析[mysqld]里面加入skip-name-resolve
- 请求binlog
- binlog不存在或者损坏
- 更新relay-log和master.info
- SQL线程
- relay-log出现问题
- 从库做写入了,一般从库只用来读,不会在上面进行写操作,因为主库同步不了从库上面的内容
- 操作对象已经存在(create)
- 操作对象不存在(insert update delete drop truncate alter)
- 约束问题、数据类型、列属性
处理方法一
处理SQL线程出现的问题
mysql> stop slave;
# 临时停止同步
mysql> set global sql_slave_skip_counter=1;
# 将同步指针向下移动一个(可重复操作)
mysql> start slave;
# 开启同步
处理方法二
vim /etc/my.cnf
# 编辑配置文件
[mysqld]
slave-skip-errors=1032,1062,1007
# 跳过的错误代码
但是以上操作都是有风险存在的
处理方法三
限制其不能修改从库
set gobal read_only=1
# 在命令行临时设置
vim /etc/my.cnf
# 编辑配置文件
[mysqld]
read_only=1
延时从库
- 普通的主从复制可能存在不足
- 逻辑损坏怎么办?
- 不能保证主库的操作,从库一定能做
- 高可用?自动failover?
- 过滤复制
- 企业中一般会延时3-6个小时
- 延时从库配置方法
mysql> stop slave;
# 临时停止同步
mysql> CHANGE MASTER TO MASTER_DELAY = 60;
# 设置延时为60秒
mysql> start slave;
mysql> show slave status\G;
SQL_Delay: 60
# 查看状态
mysql> stop slave;
mysql> CHANGE MASTER TO MASTER_DELAY = 0;
mysql> start slave;
- 恢复数据
- 停止主从
- 导出从库数据
- 主库导入数据
半同步复制
从MySQL5.5开始,支持半同步复制。之前版本的MySQL Replication都是异步(asynchronous)的,主库在执行完一些事务后,是不会关注备库的进度的。如果备库不幸落后,而更不幸的是主库此时又出现Crash(例如宕机),这时备库中的数据就是不完整的。简而言之,在主库发生故障的时候,我们无法使用备库来继续提供数据一致的服务了。
半同步复制(Semi synchronous Replication)则一定程度上保证提交的事务已经传给了至少一个备库。
出发点是保证主从数据一致性问题,安全的考虑
- 半同步复制开启方法
- 安装(主库)
mysql -uroot -p123456
mysql> show global variables like 'have_dynamic_loading';
# 查看是否有动态支持
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME'semisync_master.so';
# 安装自带插件
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
# 启动插件
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000;
# 设置超时
vim /etc/my.cnf
[mysqld]
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 1000
mysql> show global variables like 'repl%';
mysql> show global status like 'rpl_semi%';
# 检查安装
- 安装(从库)
mysql -uroot -p123456
mysql> show global variables like 'have_dynamic_loading';
# 查看是否有动态支持
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME'semisync_master.so';
# 安装自带插件
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
# 启动插件
mysql> stop slave io_thread;
mysql> start slave io_thread;
# 重启io线程使其生效
vim /etc/my.cnf
[mysqld]
rpl_semi_sync_master_enabled = 1
- 注:相关参数说明
- rpl_semi_sync_master_timeout=milliseconds
- 设置此参数值(ms),为了防止半同步复制在没有收到确认的情况下发生堵塞,如果Master在超时之前没有收到任何确认,将恢复到正常的异步复制,并继续执行没有半同步的复制操作。
- rpl_semi_sync_master_wait_no_slave={ON|OFF}
- 如果一个事务被提交,但Master没有任何slave连接,这时不可能将事务发送到其他地方保存起来。默认情况下,Master会在时间限制范围内继续等待Slave的连接,并确认该事务已经被正确的写到磁盘上。
- 可以使用此参数选项关闭这种行为,在这种情况下,如果没有Slave连接,Master就会恢复到异步复制。
- rpl_semi_sync_master_timeout=milliseconds
过滤复制
- 主库
- 白名单:只记录白名单列出的库的二进制日志
- binlog-do-db
- 黑名单:不记录黑名单列出的库的二进制日志
- binlog-ignore-db
- 白名单:只记录白名单列出的库的二进制日志
- 从库
- 白名单:只执行白名单中列出的库或者表的中继日志
- –replication-do-db=test
- –replication-do-table=test.t1
- –replication-wild-do-table=test.t*
- 黑名单:不执行黑名单中列出的库或者表的中继日志
- –replication-ignore-db
- –replication-ignore-table
- –replication-wild-ignore-table
- 白名单:只执行白名单中列出的库或者表的中继日志
- 复制过滤配置
修改从库的配置文件
vim /etc/my.cnf
[mysqld]
--replication-do-db=test1
systemctl restart mysqld
mysql -uroot -p
mysql> start slave;
- 第一次测试:
- 主库
mysql> use test1;
mysql> create table t1(id int);
-
- 从库查看结果
mysql> use test1;
mysql> show tables;
# 同步过来了
- 第二次测试:
- 主库
mysql> use test2;
mysql> create table th1(id int);
-
- 从库查看结果
mysql> show databases;
# 查看不到test2表
二、MHA高可用架构
MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0-30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA能够在较短的时间内实现自动故障检测和故障转移,通常在10-30秒以内;在复制框架中,MHA能够很好地解决复制过程中的数据一致性问题,由于不需要再现有的replication中添加额外的服务器,仅需要一个manager节点,而一个manager能管理多套复制,所以能大大地节约服务器的数量;另外,安装简单,无性能损耗,以及不需要修改现有的复制部署也是它的优势之处。
MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到一个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。
MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以独立部署在一台独立的机器上管理多个Master-Slave集群,也可以部署再一台SLave上。当Master出现故障时,它可以自动将最新数据的Slave提升为新的Master,然后将所有其他的Slave重新指向新的Master。整个故障转移过程对应用程序是完全透明的

工作流程
- 把宕机的master二进制日志保存下来。
- 找到binlog位置点最新的slave。
- 在binlog位置点最新的slave上用relay log(差异日志)修复其它slave。
- 将宕机的master上保存下来的二进制日志恢复到含有最新位置点的slave上。
- 将含有最新位置点binlog所在的slave提升为master。
- 将其它slave重新指向新提升的master,并开启主从复制。
MHA工具介绍
- MHA软件由两部分组成,Manager工具包和Node工具包
- Manager工具包主要包括以下几个工具
| masterha_check_ssh | 检测MHA的ssh-key |
|---|---|
| masterha_check_repl | 检查主从复制情况 |
| masterha_manager | 启动MHA |
| masterha_check_status | 检测MHA的运行状态 |
| masterha_master_monitor | 检测master是否宕机 |
| masterha_master_switch | 手动故障转移 |
| masterha_conf_host | 手动添加server信息 |
| masterha_secondary_check | 建立TCP连接从远程服务器 |
| masterha_stop | 停止MHA |
- Node工具包主要包括以下几个工具
| save_binary_logs | 保存宕机的master的binlog |
|---|---|
| apply_diff_relay_logs | 识别relay log的差异 |
| filter_mysqlbinlog | 防止回滚时间 |
| purge_relay_logs | 清楚中继日志 |
- MHA优点总结
- 自动故障转移快
- 主库崩溃不存在数据一致性问题
- 不需要对当前的mysql环境做重大修改
- 不需要添加额外的服务器(仅一台manager就可管理上百个replication)
- 性能优秀,可工作在半同步复制和异步复制,当监控mysql状态时,仅需要每隔N秒向master 发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制架构性能一样
- 只要replication支持的存储引擎,MHA都支持,不会局限于innodb
MHA实验环境
- 搭建三台mysql数据库,一主两从
- 克隆的另外两台机器需要改一下mysql的uuid, /application/mysql/data/auto.conf
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.6.40-linux-glibc2.12-x86_64.tar.gz
tar xzvf mysql-5.6.40-linux-glibc2.12-x86_64.tar.gz
useradd mysql -s /sbin/nologin -M
mkdir /application
mv mysql-5.6.40-linux-glibc2.12-x86_64 /application/mysql-5.6.40
ln -s /application/mysql-5.6.40/ /application/mysql # 如果版本发生改变,直接重新创建一个软连接,不用修改原来目录的名字
cd /application/mysql/support-files/
cp my-default.cnf /etc/my.cnf # 后者是linux底下自带的mysql文件
cp:是否覆盖"/etc/my.cnf"? y
cp mysql.server /etc/init.d/mysqld
cd /application/mysql/scripts
yum -y install autoconf
./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data/
vim /etc/profile.d/mysql.sh
export PATH="/application/mysql/bin:$PATH"
source /etc/profile
sed -i 's#/usr/local#/application#g' /etc/init.d/mysqld /application/mysqld/bin/mysqld_safe
vim /usr/lib/systemd/system.mysqld.service
[Unit]
Descruption=MySQL Server
Documentation=man:mysqld(8)
Documentation=https://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=Mysql
ExecStart=/application/mysql/bin/mysqld --defaults-file=/etc/my.cnf
LimitNOFILE = 5000
vim /etc/my.cnf
basedir = /application/mysql
datadir = /application/mysql/data
systemctl daemon-reload
systemctl start mysqld
systemctl enable mysqld
mysqladmin -uroot password '123456'
mysql -uroot -p123456
基于GTID的主从复制
- 先决条件
- 主库和从库都要开启binlog
- 主库和从库server-id不同
- 要有主从复制用户
- uuid:tid(事务id)
- 优势
- 效率高,速度快,在每一个库都开启一个SQL线程
- row,节省网络资源,磁盘资源,内存使用率
- 不需要找pos定位
- 将主从信息记录在tables中,提高可用性
- 支持所有复制,包括延时复制
主库操作
- 修改配置文件
vim /etc/my.cnf
[mysqld]
server_id=1
# 主库server-id为1,从库不等于1
log_bin=mysql-bin
# 开启binlog日志
skip-name-resolv
# 跳过域名解析
- 创建主从复制用户(所有主机)
mysql -uroot -p123456
mysql> grant replication slave on *.* to slave@'192.168.64.%' identified by '123456';
# 创建slave用户
从库操作
- 修改配置文件
vim /etc/my.cnf
[mysqld]
server_id=5
# 主库server-id为1,从库不等于1
log_bin=mysql-bin
# 开启binlog日志,因为可能会成为一个主库
重启 systemctl restart mysqld
第二台从库:
vim /etc/my.cnf
[mysqld]
server_id=10
# 主库server-id为1,从库不等于1
log_bin=mysql-bin
# 开启binlog日志
重启 systemctl restart mysqld
注:在以往如果是基于binlog日志的主从复制,则必须要记住主库的master状态信息。
mysql> show master status;
开启GTID
mysql> show global variables like '%gtid%';
# 没开启之前先看一下GTID的状态
vim /etc/my.cnf
[mysqld]
# 主库从库都需要修改
gtid_mode=ON
log_slave_updates
# 开启slave binlog同步
enforce_gtid_consistency
# 不允许任何违反GTID一致性
# 重启数据库
systemctl restart mysqld
mysql> show global variables like '%gtid%';
# 检查GTID的状态
注:主库从库都需要开启GTID否则在主从复制的时候就会报错
mysql -uroot -p123456
mysql> change master to
master_host='192.168.64.129',
master_user='slave',
master_password='123456',
#master_log_file='mysql-bin.000001',
#master_log_pos=120;
master_auto_position=1; #自动找位点
mysql> start slave;
# 开启slave
mysql> show slave status\G;
# 查看状态
- 从库设置
不删除从库的relaylog
mysql> set global relay_log_purge = 0;
# 禁用自动删除relay log功能
mysql> set global read_only=1;
# 设置只读
vim /etc/my.cnf
[mysqld]
relay_log_purge = 0
部署MHA
环境准备(所有节点)
工具包下载地址
cd && wget https://download.s21i.faiusr.com/23126342/0/0/ABUIABBPGAAg3OHUiAYolpPt7AQ.zip?f=mysql-master-ha.zip&v=1628778716
yum install perl-DBD-MySQL -y
# 安装依赖包
unzip mysql-master-ha.zip
cd mysql-master-ha
# 进入安装包存放目录
ls
rpm -ivh mha4mysql-node-0.56-0.e16.noarch.rpm
# 安装node包
mysql -uroot -p123456
mysql> grant replication slave on *.* to mha@'192.168.64.%' identified by 'mha';
# 添加mha管理账户
mysql> select user,host from mysql.user;
# 查看是否添加成功
mysql> select user,host from mysql.user;
# 主库上创建,从库上会自动复制,(在从库上查看)
- 命令软连接(所有节点)
ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /application/mysql/bin/mysql /usr/bin/mysql
# 如果不创建命令软连接,检测mha复制情况的时候会报错
node节点部署完了
- 部署管理节点(mha-manager:mysql-db03),一个管理者
yum install -y epel-release
# 使用epel源
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManger perl-Time-HiRes
# 安装manager依赖包
cd ~/mysql-master-ha && rpm -ivh mha4mysql-manager-0.56-0.e16.noarch.rpm
# 安装manager包
- 编辑配置文件(manager节点)
mkdir -p /etc/mha
# 创建配置文件目录
mkdir -p /var/log/mha/app1
# 创建日志目录
vim /etc/mha/app1.conf
[server default]
manager_log=/var/log/mha/app1/manager.log
manager_workdir=/var/log/mha/app1
master_binlog_dir=/application/mysql/data
user=mha
password=mha
ping_interval=2
repl_password=123456
repl_user=salve
ssh_user=root
[server1]
hostname=192.168.64.129
port=3306
[server2]
hostname=192.168.64.133
port=3306
candidate_master=1
check_repl_delay=0
[server3]
hostname=192.168.64.135
port=3306
- 配置ssh信任(所有节点)
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa > /dev/null 2>&1
ssh-copy-id -i /root/.ssh/id_dsa.pub root@192.168.64.129
ssh-copy-id -i /root/.ssh/id_dsa.pub root@192.168.64.133
ssh-copy-id -i /root/.ssh/id_dsa.pub root@192.168.64.135
- 启动测试(manage节点)
# masterha_check_ssh --conf=/etc/mha/app1.cnf
# 测试ssh
# masterha_check_repl --conf=/etc/mha/app1.cnf
# 测试复制
- 启动MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ingnore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
# 启动
masterha_check_status --conf=/etc/mha/app1.cnf
# 检测状态
- 切换master测试
mysql> show slave status;
# 停掉主库
systemctl stop mysqld
#在后面两个从库上分别看slave的状态
mysql> show slave status;
11万+

被折叠的 条评论
为什么被折叠?



