一.mysql 二进制日志格式
- 基于段的格式 binlog_format=STATEMENT
【记录 sql】
优点
- 日志记录量相对较小,节约磁盘和网络 I/O
- 只对一条记录修改、插入时,row 格式日志量小于端格式
缺点
- 必须记录上下文信息,保证主从记录相同
- 特定函数 UUID().user(),非确定性函数无法主从复制
查看当前二进制日志格式
show variables like 'binlog_format';
临时修改参数
set session binlog_format=statement;
刷新 binlog,产生新的 binlog 文件(名字如 mysql-bin.xxxxxx)
flush logs;
查看 binlog 内容
mysqlbinlog mysql-bin.000001 #查看名为mysql-bin.000001的binlog内容
2.基于行的日志格式 binlog_format=ROW(mysql5.7 之后默认使用这种格式)
【记录每一行的修改】
优点
- ROW 格式可以避免 mysql 主从复制中出现的主从不一致
- 对每一行数据的修改比基于段的复制更高效
- 误操作且没有备份时,可通过反向执行二进制日志记录的操作来恢复数据
缺点
- 记录日志量较大
- 控制 row 记录的方式:binlog_row_image=[FULL|MINIMAL|NOBLOB]
- FULL 全部记录;MINIMAL 同时多行操作只记录一行;NOBLOB 不修改 BLOB、TEXT 类型的字段时不会记录此字段
查看 row 格式的 binlog
mysqlbinlog -vv mysql-bin.000003 | more
3. 混合日志格式 binlog_format=MIXED
特点
- 根据 sql 语句由系统决定是使用基于段的还是基于行的格式
- 数量的大小由所执行的 sql 语句决定
建议使用 mixed 或者 row,row 格式安全些较高,并要设置 minimal 这种方式
二、mysql 主从复制
1. 复制方式
(1)基于 SQL 语句的复制 SBR(日志格式使用的是 STATEMENT)
优点
- 日志记录量相对较小,节约磁盘和网络 I/O
- 并不强制要求主从数据库的表定义完全相同
- 相比于行的复制更为灵活
缺点
- 对于非确定性事件,无法保证主从复制数据的一致
- 对于存储过程、触发器、自定义函数进行的修改也可能造成数据的不一致
- 相比于基于行的复制从数据库上执行时需要更多的行锁
(2)基于行的复制 RBR(日志格式使用的是 ROW)
优点
- 可以应用于任何 SQL 的复制,包括非确定性函数、存储过程等
- 可以减少数据库锁的使用
缺点
- 要求主从数据库的表结构相同,否则会中断
- 无法再从服务器上单独执行触发器
(3)混合模式
- 使用 MIXED
2. 复制工作方式
(1)主将变更写入二进制日志
(2)从读取主的二进制日志,并写入到 relay_log 中
(3)在从数据库上重放 relay_log 中的日志
3. 基于日志点的复制
(1)在主 DB 服务器上建立复制账号
create user 'repl'@'IP段' identified by '密码'
grant replication slave on *.* to 'repl'@'IP段'
IP段可以形如192.168.3.%
(2)主数据库配置
bin_log = mysql-bin
server_id = 100
(3)从服务器配置
bin_log = mysql-bin
server_id = 101
relay_log = mysql-relay-bin
log_slave_update = on [可选]
read_only = on [可选]阻止写操作
(4)从数据库初始化
主服务器备份
mysqldump --master-data=2 --single-transaction[对仅有innodb的数据库,对有myisam和innodb混合的数据库使用--lock-all-tables]
mysqldump --single-transaction --master-data --triggers --routines --all-databases -u root -p >> all.sql
xtrabackup --slave-info [推荐]
从服务器导入
mysql -u root -p < all.sql
(5)启动复制链路
在从服务器 msql 命令行执行,最后两个参数可以在 mysqldump 生成的文件中找到
CHANGE MASTER TO MASTER_HOST='master_host_ip',
MASTER_USER='xxx',
MASTER_PASSWORD='xxx',
MASTER_LOG_FILE='mysql_log_file_name',
MASTER_LOG_POS=4;
然后启动
start slave;
可查看进程[mysql 命令行中]
show processlist
查看从服务器
show slave status \G
(6)优缺点
优点
- bug 相对少,最早支持
- 对 sql 查询没有任何限制
- 故障处理比较容易
缺点
- 故障转移时重新获取逐日志点信息比较困难
4. 基于 GTID 的复制
GTID 即全局事务 ID,其保证为每一个在主上提交的事务,在复制集群中可以生成一个唯一的 ID
GTID=source_id:transaction_id
source_id 主库的 uuid 值
transaction_id 事务的 id
(1)主 DB 上简历复制账号
create user 'repl'@'IP段' identified by '密码'
grant replication slave on *.* to 'repl'@'IP段'
IP段可以形如192.168.3.%
(2)主数据库配置
bin_log=/usr/local/mysql/log/mysql-bin
server_id=100
gtid_mode=on
enforce-gtid-consistency强制gtid一致性
log-slave-updates=on在mysql5.7以后不需要开启,会增加从服务器资源消耗
(3)从数据库配置
server_id=101
relay_log=/usr/local/mysql/log/relay_log
gtid_mode=on
enforce-gtid-consistency
log-slave-updates=on
read_only=on[建议]
master_info_repository=TABLE[建议]
relay_log_info_repository=TABLE[建议]
(4)初始化从服务器
(5)启动
CHANGE MASTER TO MASTER_HOST='master_host_ip',
MASTER_USER='xxx',
MASTER_PASSWORD='xxx',
MASTER_AUTO_POSITION=1;
(6)优缺点
优点
- 方便进行故障转移
- 从库不会丢失主库任何修改
缺点
- 故障处理比较复杂
- 对执行的 sql 有限制
(7)选择
- GTID 是 mysql5.6 及以后才支持的
- 复制架构及主从切换方式:GTID 方便切换
- 所使用的高可用管理组件
- 对应用支持度
5.mysql 复制拓扑
(1)MYSQL5.7 之前一个从库只能一个主库,之后可以一从多主
(2)一主多从
优点
- 配置简单
- 多个从库分担读负载
用途
- 为不同业务使用不同从库(前后台查询)
- 一台从库放到远程 IDC,用做灾备恢复
- 分担主库的读负载
(3)主-主复制拓扑
主主模式(不建议)
- 两个主中所操作的表最好能分开
- 使用下面两个参数自增 id 的生成【auto_increment_increment=2;auto_increment_offset=1|2(一台为 1 一台为 2)】
主备模式(一台对外服务)
- 确保两台服务器初始数据相同
- 确保两台服务器启动 binlog,并且 server_id 不同
- 都启用 log_slave_updates 参数
- 初始的备库使用 read_only
(4)拥有备库的主主复制拓扑
(5)级联复制
6.复制性能优化
影响主从延迟的因素
- 主库写入二进制日志的时间(大事务);解决方式:控制主库的事务大小,分割大事务
- 二进制日志传输时间;解决方式:使用 mixed 日志格式,或者设置 set binlog_row_image=minimal;
- 默认情况下从只有一个 sql 线程,主上并发的修改在从上变成串行;解决方式:使用多线程复制(5.6 及以后)
配置多线程复制
- stop slave
- set global slave_parallel_type='logical_clock' (使用逻辑时钟方式,5.7 支持)
- set global slave_parallel_workers=4;
- start slave;
show variables like 'slave_parallel_type';
7.复制问题
(1)数据损坏或丢失引起主从复制错误
- 主库或从库宕机引起错误;解决方式:使用跳过二进制日志事件或者注入空事务先恢复中断的复制链路,再对比主从数据
- 主库二进制日志损坏
- 备库上的中继日志损坏
(2)在从库数据修改造成主从复制错误
(3)不唯一的 server_id 或者 server_uuid
(4)max_allow_packet 设置引起的主从复制错误
8.复制不能解决的问题
- 不能分担主数据库的写负载;解决方式:分库分表
- 不能自动进行故障转移和主从切换
- 不能提供读写分离
三、高可用架构
服务器磁盘空间耗尽:备份或者各种查询日志突增导致磁盘空间占满,mysql 无法记录二进制日志,无法处理新的请求
- 建立监控报警系统
- 对备份数据进行恢复测试
- 正确配置数据库环境(从要 read_only)
- 对不需要的数据进行归档和清理
增加系统冗余,保证尽快恢复
- 避免存在单点故障
- 主从切换及故障转移
单点故障
- 利用 SUN 共享存储或者 DRDB 磁盘恢复解决单点故障
- 利用多谢集群或者 NDB 集群来解决(pxc 架构)
- 利用主从复制来解决
解决主从中主服务器的单点故障
- 主服务器切换后,如何通知应用新的主服务器 ip 地址
- 如何检查主服务器是否可用
- 如何处理从服务器和新主服务器之间的复制关系
- 解决方式:使用 MMM 或者 MHA
(一).MMM 架构
1.作用:监控和管理 MySQL 的主主复制拓扑,并在当前主服务器失效时,进行主和主备服务器之前的服从切换和故障转移操作。
MMM 所需要的资源
拓扑图
2.配置步骤(先配置主主复制)
(1)备份主数据库
mysqldump --master-data=2 --single-transaction --lock-all-tables --all-databases -u root -p > all.sql
(2)数据库导入数据(用于另一个主服务器和其他从服务器的数据导入)
mysql -u root -p < all.sql
(3)一个主数据库配置复制链路(192.168.3.101)(此操作在 mysql 的命令行中)
CHANGE MASTER TO MASTER_HOST='192.168.3.100',
MASTER_USER='xxx',
MASTER_PASSWORD='xxx',
MASTER_LOG_FILE='mysql_log_file_name',
MASTER_LOG_POS=4;#偏移量使用备份文件all.sql里面备份时间点的偏移量(搜索关键字MASTER_LOG_FILE)
然后启动
start slave;
查看当前服务器(可以看到当前库的二进制日志名称 File,和偏移量 Position)
show slave status \G
(4)另一个主数据库配置复制链路(192.168.3.100),从而形成主主复制
CHANGE MASTER TO MASTER_HOST='192.168.3.101',
MASTER_USER='xxx',
MASTER_PASSWORD='xxx',
MASTER_LOG_FILE='mysql_log_file_name',#取192.168.3.101的二进制日志名称
MASTER_LOG_POS=4;#取192.168.3.101的偏移量
然后启动
start slave;
(5)配置从数据库复制链路(192.168.3.102)
CHANGE MASTER TO MASTER_HOST='192.168.3.100',
MASTER_USER='xxx',
MASTER_PASSWORD='xxx',
MASTER_LOG_FILE='mysql_log_file_name',
MASTER_LOG_POS=4;#偏移量使用备份文件all.sql里面备份时间点的偏移量(搜索关键字MASTER_LOG_FILE)
然后启动
start slave;
(6)更新每个数据库服务器的 yum 源
wget http://mirrors.opencas.cn/epel/epel-release-latest-6.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rmp
rmp -ivh epel-release-latest-6.noarch.rpm #安装
rmp -ivh remi-release-6.rpm
vim /etc/yum.repos.d/remi.repo #修改[remi]中的enabled=1
vim /etc/yum.repos.d/epel.repo #修改[epel]中,打开baseurl注释,注释掉mirrorlist
(7)mmm 组件安装
yum install mysql-mmm-agent.noarch -y #安装 mmm 代理,每个服务器都安装
yum install mysql-mmm* #安装监控组件,监控服务器上安装,此处是在一个从服务器上安装。(监控服务器可以单独设立,也可以利用一个从服务器来混合使用)
(8)mysql 用户创建(在主服务器 100 上创建)
grant replication client on *.* to 'mmm_monitor'@'192.168.3.%' identified by '123456'; #监控用户
grant super,replication client,process on *.* to 'mmm_agent'@'192.168.3.%' identified by '123456'; #代理用户
grant replication slave on *.* to 'repl'@'192.168.3.%' identified by '123456'; #复制用户,此用户应在前面配置复制链路前添加,复制链路中使用的就是此用户
(9)mmm 配置文件
数据库结点配置
vim /etc/mysql-mmm/mmm_common.conf #所有服务器都配置
replication_user repl
replication_password 123456
agent_user mmm_agent
agent_password 123456
<host db1>
ip 192.168.3.100
mode master
peer db2
host>
<host db2>
ip 192.168.3.101
mode master
peer db1
host>
<host db3>
ip 192.168.3.102
mode slave
host>
<role writer>
hosts db1,db2
ips 192.168.3.90 #虚拟ip
mode exclusive
role>
<role reader>
hosts db1,db2,db3
ips 192.168.3.91,192.168.3.92,192.168.3.93 #虚拟ip
mode balanced
role>
vim /etc/mysql-mmm/mmm_agent.conf #所有服务器(代理服务器)
this db1 #各个服务器改成自己的代号:db2,db3.....
监控结点配置
vim /etc/mysql-mmm/mmm_mon.conf #监控服务器,只列出要修改的
<monitor>
ping_ips 192.168.3.100,192.168.3.101,192.168.3.102 #最好加上网关,以监控网络有效性
monitor>
<host default>
monitor_user mmm_monitor
monitor_password 123456
host>
(10)启动
-
/etc/init.d/mysql-mmm-agent start
-
#启动代理,在所有代理服务器执行,此处100、101、102都是代理服务器
-
/etc/init.d/mysql-mmm-monitor start
-
#启动监控,在监控服务器执行,此处混合使用的102服务器作为监控
-
mmm_control show #在监控服务器执行,可查看当前服务状态
(11)特点
- 不支持 GTID 复制,只支持基于日志点的复制
- 发布比较早,最新版本 10 年发布
- 没有负载均衡的功能
- 主从切换容易造成数据丢失
- MMM 监控服务存在单点故障
(二).MHA 架构
1.简介
(1)特点
- 只监控主数据库服务器是否可用
- 当主数据库不可用时,在多个从数据库中选举出新的主数据库服务器
- 提供了主从切换和故障转移
- 可以与半同步复制结合
(2)主从切换过程
- 尝试从出现故障的主数据库保存二进制日志
- 从多个被选从服务器中选举出新的备选主服务器
- 在备选主服务器和其他从服务器同步差异二进制数据
- 重放从原来主服务器上保存的二进制日志
- 提升备选主为新的主服务器
- 迁移集群中其它从 DB 为新主 DB 的从服务器
2.配置
使用 masterha_check_ssh 和 masterha_check_repl 对配置进行校验
拓扑图
(1)
(1)建立主从复制集群
- 此处建立的是基于 GTID 的复制,需要所有服务器都要设置 gtid_mode=on
- 需要添加 repl 用户
- 需要各个从数据库数据初始化,保持数据一致
- 启动复制链路(参考上面的--基于 GTID 的复制)
(2)先配置免认证登陆
- 使用
ssh-keygen
生成秘钥 - 使用
ssh-copy-id -i /root/.ssh/id_rsa '-p 22 root@192.168.3.100'
来复制公钥到其他节点(本机也要添加,当本机作为主时使用);所有节点都要执行此操作。
【node 和 manager 软件包下载】
软件包下载 https://drive.google.com/drive/folders/0B1lu97m8-haWeHdGWXp0YVVUSlk
(3)node 软件包安装(服务结点)
- 先安装依赖包,需要的是
yum -y install perl-DBD-MySQL perl-DBI.x86 ncftp
- 此处使用的 rpm 包
rpm -ivh mha4mysql-node-*-*.noarch.rpm
- 所有节点都要安装(除监控结点)
(4)manager 软件包安装(监控结点)
安装依赖
yum -y install perl-Config-Tiny.noarch perl-Time-HiRes.x86_64 perl-Parallel-ForkManager perl-Log-Dispatch-Perl.noarch perl-DBD-MySQL perl-DBI.x86 ncftp
安装包
rpm -ivh mha4mysql-manager-*-*.noarch.rpm
(5)管理服务器增加配置文件
在/etc/mha/mysql_mha.cnf
[server default]
user=mha#MHA用于管理数据库的用户,备选主都增加,给privileges权限
password=123456
manager_workdir=/home/mysql_mha
manager_log=/home/mysql_mha/manager.log
remote_workdir=/home/mysql_mha#其他节点都建立
ssh_user=root
repl_user=repl#复制用户
repl_password=123456
ping_interval=1 #检查主是否能连同的时间间隔
master_binlog_dir=/home/mysql/sql_log
master_ip_failover_script=/user/bin/master_ip_failover #用于虚拟IP迁移脚本
#通过多路径检测master是否可用,脚本mha自带
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.3.101 -s 192.168.3.102 -s 192.168.3.100 -s 网关IP
[server1]
hostname=192.168.3.100
candidate_master=1#可以作为备选的主
[server2]
hostname=192.168.3.101
candidate_master=1#可以作为备选的主
[server3]
hostname=192.168.3.102
no_master=1#不可作为备选的主
脚本/user/bin/master_ip_failover #用于虚拟 IP 迁移脚本
-
#!/usr/bin/env perl
-
use strict;
-
use warnings FATAL => 'all1;
-
use Getopt::Long;
-
my (
-
$command,$orig_master_host,$orig_master_ip,$ssh_user,
-
$orig_master_port, $new_master_host, $new_master_ip,$new_master_port,
-
$orig_master_ssh_port,$new_master_ssh_port,$new_master_user,$new_master_password
-
);
-
my $vip = '192.168.3.90/24l';
-
my $key = '1';
-
my $ssn_start_vip = "sudo /sbin/ifconfig ethO:$key $vip";
-
my $ssh_stop_vip = "sudo /sbin/ifconfig ethO:$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,
-
'orig_master_ssh_port=i' => \$orig_master_ssh_port,
-
'new一master一host=s' => \$new_master_host,
-
'new_master_ip=s' => \$new_master_ip,
-
'new_master_port=i' => \$new_master_port,
-
'new_master_ssh_port' => \$new_master_ssh_port,
-
'new_master_user' => \$new_master_user,
-
'new一master_password' => \$new_master_password
-
);
-
exit &main();
-
sub main {
-
$ssh_user = defined $ssh_user ? $ssh_B|ser : ' root';
-
print "\n\nIN SCRIPT TEST====$ssh_user|$ssh_stop_vip==$ssh_user|$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_vi();
-
$exit_code = 0;
-
};
-
if ($@) {
-
warn "Got Error: $@\n";
-
exit $exit_code;
-
}
-
exit $exit_code;
-
}
-
elsif ( Scommand 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 $exit一code;
-
}
-
elsif ( $command eq "status" ) {
-
print "Checking the Status of the script.. OK \n";
-
exit 0;
-
}
-
else {
-
&usage();
-
exit 1;
-
}
-
}
(6)运行
测试配置是否正确
masterha_check_ssh --conf=/etc/mha/mysql_mha.cnf
复制环境检测
masterha_check_repl --conf=/etc/mha/mysql_mha.cnf
运行 mha(此处放到后台运行)
nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf &
mha 不会自动配置虚拟 IP(但可以利用 master_ip_failover 脚本,在主服务器更换时自动迁移走),需要手动在主服务器配置
ifconfig eth0:1 192.168.3.90/24
(7)优点
- Perl 开发、开源
- MHA 可以支持基于 GTID 的复制
- MHA 在故障转移时更不易产生数据丢失
- MHA 同一个监控结点可以监控多个集群
(8)缺点
- 需要编写脚本或者利用第三方工具来实现 Vip(虚拟 IP)的配置(上方 master_ip_failover 脚本就是)
- MHA 启动后只会对主数据库进行监控,其他比如复制链路出现问题等不会监控到
- 需要机遇 SSH 免认证配置,存在一定的安全隐患
- 没有提供从服务器的读负载均衡功能
(三)读写分离
方式:
(1)程序控制(灵活,不增加故障点,性能损耗较少);
(2)中间件控制
1.中间件控制
(1)工具:mysql-proxy;maxScale
(2)特点:
- 中间件根据查询语法分析,自动完成读写分离
- 对程序透明,已有程序不需要修改
- 增加中间层,对效率有损耗
- 对于延迟敏感业务无法自动在主库执行
(四)读的负载均衡
工具:软件(LVS,Haproxy,MaxScale);硬件(F5)
(五)MaxScale
1.插件
- Authentication 认证插件
- Protocal 协议插件(客户端到 MaxScale,MaxScale 到后端数据库的协议)
- Router 路由插件(读写分离(readwritesplit)、读负载均衡(readconnroute)由此模块实现)
- Monitor 监控插件(用于监控后台数据库是否正常)
- Filter&Logging 过滤和日志插件(提供了数据库防火墙功能)
2.安装
(1)下载:到此页面下载 https://mariadb.com/downloads/maxscale
(2)安装依赖
yum -y install libaio.x86_64 libaio-devel.x86_64 novacom-server.x86_64
(3)安装
rpm -ivh maxScale-xxxxx.x84_64.rpm
3.配置
(1)先在主数据库建立 maxScale 监控使用的账号
create user scalemon@'192.168.3.%' identified by '123456';
grant replication slave, replication client on *.* to scalemon@'192.168.3.%' ;
(2)建立 maxScale 路由模块使用的账号(只读权限)
create user scale@'192.168.3.%' identified by '123456';
grant select on *.* to scale@'192.168.3.%' ;
(3)生成加密的密码(可选)
maxkey #生成加密秘钥到/var/lib/maxscale目录
maxpasswd /var/lib/maxscale 123456 #生成加密的密码,此处123456是密码
(4)配置文件 /etc/maxscale.cnf
此处只记录需要修改的
-
threads=4 #一般最多为8
-
[server1]
-
type=server
-
address=192.168.3.100
-
port=3306
-
protocol=MySQLBackend
-
[server2]
-
type=server
-
address=192.168.3.101
-
port=3306
-
protocol=MySQLBackend
-
[server3]
-
type=server
-
address=192.168.3.102
-
port=3306
-
protocol=MySQLBackend
-
[MySQL Monitor]
-
servers=server1,server2,server3
-
user=scakemon #监控用的用户
-
passwd=123456 #如果前面生成了加密的密码,可以填在此处
-
monitor=1000 #此处代表监控每秒发起一次
-
[Read-Only Service] #此处是配置读负载均衡;演示项目要配置读写分离,遂删除了此模块配置
-
[Read-Write Service]
-
servers=server1,server2,server3
-
user=maxscale
-
passwd=123456
-
max_slave_connections=100% #最大可用从服务器数量
-
max_slave_replication_lag=60 #(秒)从服务器的延迟大于此值时,就不参与读写分离
-
[Read-Only Listener] #只读监听;演示项目没有使用只读服务,遂删除了此模块配置
-
[Read-Write Listener]
-
port=4006 #此端口可用于程序连接使用,代替直连后端的mysql服务器
(5)启动
maxscale --config=/etc/maxscale.cnf
(6)maxscale 后台管理
maxadmin --user=admin --password=mariadb
##############以下为进入后的命令##################
list servers #列出所有服务器
show dbuers "Read-Write Service" #列出读写分离模块的用户
最终高可用架构的拓扑图
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于