Mysql数据库之集群进阶

news2025/5/18 17:49:48

一、日志管理

5.7版本自定义路径时的文件需要自己提前创建好文件,不会自动创建,否则启动mysql会报错

错误日志

rpm包(yum)    /var/log/mysql.log  默认错误日志

###查询日志路径
[root@db01 ~]# mysqladmin -uroot -pEgon@123 variables | grep -w log_error 
或者
[root@db01t ~]# mysql -uroot -pEgon@123
mysql> show variables like '%log_error%';

###设置错误日志路径
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
#绝对路径
log_error=/var/log/mysql.errlog
#相对路径
#log_error=mysql.errlog
 
[root@localhost ~]# touch /var/log/mysql.errlog
[root@localhost ~]# chmod 640 /var/log/mysql.errlog 
[root@localhost ~]# chown mysql.mysql /var/log/mysql.errlog 
[root@localhost ~]# systemctl restart mysqld

###log_warnings参数

mysql5.6

log_warnings的值为0,表示不记录警告信息。
log_warnings的值为1,表示警告信息一并记录到错误日志中。
log_warnings的值大于1,表示"失败的连接"的信息和创建新连接时"拒绝访问"类的错误信息也会被记录到错误日志中。
### 
mysql5.5中log_warnings参数的默认值为1
mysql5.7中log_warnings参数的默认值为2
mysql> show variables like "%log_warnings%";

###log_error_verbosity参数

mysql5.7
# 它有三个可选值, 分别对应:
# log_error_verbosity=1:错误信息;
# log_error_verbosity=2:错误信息和告警信息;(推荐)
# log_error_verbosity=3(默认值就是3):错误信息、告警信息和通知信息。

事务日志

详见mysql数据库进阶

查询日志 

1.默认是关闭的
一般不会开启,因为哪怕你开启事务一顿操作,最后不提交也会记录,生产上程序跑sql很多,会非常非常占地方,从来都不启动,要看操作去binlog
 
2.开启
[root@db01 ~]# vim /etc/my.cnf
general_log=on
general_log_file=/var/log/select.log
#可以使用set global general_log=on;设置
 
[root@localhost ~]# touch /var/log/select.log
[root@localhost ~]# chmod 640 /var/log/select.log
[root@localhost ~]# chown mysql.mysql /var/log/select.log
[root@localhost ~]# systemctl restart mysqld

3.查看一般查询日志
[root@db01 ~]# mysqladmin -uroot -pEgon@123 variables|grep general_log 
或者
[root@db01 ~]# mysql -uroot -pEgon@123
mysql> show variables like '%gen%';

慢查询日志

  • 将mysql服务器中影响数据库性能的相关SQL语句(不论是什么语句,增删改查)记录到日志文件
  • 通过对这些特殊的SQL语句分析并改进,提高数据库性能
  • 全表扫描日志一定记录到慢日志
  • 慢日志+explain工具=快速定位进行sql分析并优化  (慢日志--定位  explain--分析)

配置

#默认慢日志是不开启的 
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
#指定是否开启慢查询日志
slow_query_log = 1
#指定慢日志文件存放位置(默认在data)
slow_query_log_file=/var/log/slow.log
#设定慢查询的阀值(默认10s)
long_query_time=0.05
#不使用索引的慢查询日志是否记录到日志
log_queries_not_using_indexes=ON
#查询检查返回少于该参数指定行的SQL不被记录到慢查询日志,少于100行的sql语句查询慢的话不记录,一般不使用
#min_examined_row_limit=100  # 鸡肋
 
执行下述命令
touch /var/log/slow.log
chmod 640 /var/log/slow.log
chown mysql.mysql /var/log/slow.log
systemctl restart mysqld

测试

测试:BENCHMARK(count,expr)
SELECT BENCHMARK(50000000,2*3); 
#执行卡死,查看执行的sql执行时间,如果停不下来 可以 kill id
show processlist;
kill 3;

或者用
insert city_new select * from city;
insert city_new select * from city_new;
insert city_new select * from city_new;
insert city_new select * from city_new;

查看

mysqldumpslow -s r -t 10 /var/log/slow.log 
得到按照时间排序的前10条里面含有左连接的查询语句
参数说明:
-s:指定排序方式
    c、t、l、r分别是按照记录次数、时间、查询时间、
    返回的记录数来排序,ac、at、al、ar,表示相应的倒叙 
-t:是top n的意思,即为返回前面多少条的数据; 
-g:后边可以写一个正则匹配模式,大小写不敏感的;

tail -f /var/log/slow.log 

二、binlog日志

             

                  

binlog的作用

(1)数据恢复:可以基于时间点恢复,以及根据其进行增量与差异备份(配合全量备份使用)
(2)mysql主从复制,通过binlog实现数据复制

工作模式

1、语句模式
      binlog_format=statement(mysql5.7.6之前的默认级别)

# 语句模式介绍
只记录对数据库做出修改的sql语句,不记录该sql的上下文信息

# 优点
不需要记录细到每一行数据的更改变化,因此,binlog日志量小,IO压力小,性能较高 
例如:
    一条语句修改了100万行,该模式下只需要记录下该条语句即可
 
# 缺点
日志中记录的sql语句可能有上下文依赖,此时脱离了当前数据库环就无法运行了,因此该模式下容易出现主从不一致的问题。
例如:
    主库记录的某条sql语句引用了主库中的函数、触发器、存储过程等特殊功能
    在从库上接收了该sql之后,可能就无法正确运行,从而主从库数据不一致的问题。
 
ps:row模式是基于每一行来记录变化的,所以不会出现类似的问题。
 
例如
开启binlog日志后,我们在某个库下自定义函数,若想定义成功需要先设置配置项
set global log_bin_trust_function_creators=TRUE;   
但还是不推荐,因为你定义的函数后续语句再次进行调用时极度容易找不到,只存在于当前的位置
 
# 应用场景
sql语句对mysql内置功能依赖比较少:不使用存储过程/触发器/函数,可以使用该模式,否则还是推荐行级模式

2、行级模式
      binlog_format=row(mysql5.7.6之后+8.0默认级别)

# 行级模式介绍
记录每一行数据修改的细节,即哪一条记录被修改了,修改成什么样了 
例如:执行语句(f1参照上例,此处略)
insert into t1(name) values(concat("egon",f1(1,2))); 
如果使用row模式,那么日志中会记录插入了一条新记录,记录中的name字段值为'egon3'
 
# 优点
相当于把上下文依赖都记录了下来,可以更方便查看每一条数据修改的细节,并且不会出现某些特定情况下的存储过程或function以及trigger的调用和触发无法被正确复制的问题,即该模式下主从复制强一致,数据最安全。
 
# 缺点
日志量大 
例如
    一条语句修改了100万行,语句模式下只需要记录一条语句即可
    而行级模式却修改记录下100万行的修改记录,binlog日志的量可能会大得惊人。
 
# 应用
sql语句对mysql内置功能依赖比较多,希望数据最安全,复制强一致的场景推荐行级模式

3、混合模式 
      binlog_format=mixed  一般不用

相关概念及参数

  • 事件events
    binlog中的每一条记录当作一个“事件”
  • 位置position(字节数)
    把整个二进制文件想象成一个字节序列,从第一个字节开始记录,每一个事件占对应据一个位置,依次类推

  • server_id
    服务ID,主从库必须不一样,建议数字为:ip+端口,5.7.3以后版本,必须指定
  • log-bin
    此变量用于控制是否开启二进制日志,而且这是一个只读变量,默认值为OFF 
           当我们启动数据库以后,在当前数据库连接中查看此变量的值,此变量值可能为OFF,表示不记录二进制日志,如果想要记录二进制日志,只需将此值设置为二进制日志的文件名即可
    示例:
    log-bin=/var/lib/mysql/mybinlog #绝对路径
    # log-bin=mybinlog #也可以用相对路径, 会在$datadir下产生mysqlbinlog-00000N
  • log_bin_index
    不设置的话,会根据log_bin值名称自动生成mybinlog.index
    log_bin_index=var/lib/mysql/mybinlog.index 
  • sql_log_bin
    默认为ON
    此变量用于标识当前会话中的操作是否会被记录于二进制日志
  • binlog_format
    此变量的值决定了二进制日志的记录方式,此变量的值可以设置为statement、row、mixed,分别表示以语句的形式记录二进制日志,以数据修改的形式记录二进制日志,以混合的方式记录二进制日志,安全保险起见,推荐使用row的方式记录
  • sync_binlog
    binlog刷盘策略
  • 其他参数
    #打开才能查看详细记录,默认为off
    binlog_rows_query_log_events=on  
    #表示自动删除10天以前的日志
    expire_logs_days=10  
    # full,minimal,noblob分别表示binlog中内容全记录,只记录被操作的,和不记录二进制
    binlog_row_image=full #(full,minimal,noblob)

管理

查看配置项

show variables like '%log_bin%';    #查看xxx变量
show variables like '%binlog%';
show variables like '%binlog_format%';
show variables like '%server%';
show variables like 'expire_logs_days'; -- 过期日志天数
 
# 或者
[root@db01 ~]# mysqladmin -uroot -pEgon@123 variables |grep -w log_bin

开启

1.默认是关闭的 
2.配置开启binlog
vim /etc/my.cnf
[mysqld]
server_id=1
log-bin=/var/lib/mysql/mybinlog 
binlog_format='row' #(row,statement,mixed),不建议随意去修改binlog工作模式    
binlog_rows_query_log_events=on 
max_binlog_size=100M 

查看

#查看日志名、状态、事件

show binary logs;   show master logs; #等效
show master status;                          #查询当前正在用的binlog
show binlog events in 'mybinlog.000002';  #显示指定二进制日志文件中的所有事件详情
show binlog events in 'mybinlog.000002' limit 3;

###查看日志内容
mysqlbinlog mybinlog.000002 
按时间:
# mysqlbinlog mybinlog.000002 --start-datetime="2022-11-05 10:02:56"
# mysqlbinlog mybinlog.000002 --stop-datetime="2022-11-05 11:02:54"
# mysqlbinlog mybinlog.000002 --start-datetime="2022-11-05 10:02:56" --stop-datetime="2022-11-05 11:02:54"  
按字节数:
# mysqlbinlog mybinlog.000002 --start-position=337
# mysqlbinlog mybinlog.000002 --stop-position=662
# mysqlbinlog mybinlog.000002 --start-position=337 --stop-position=662
 

如果是行级模式,想要看懂详细内容则需要加上额外参数,但是仅用于看懂内容,如果要用于还原数据,还是应该去掉额外的参数并将内容定位到文件中
#mysqlbinlog --base64-output=decode-rows -vvv mybinlog.000002  # 仅用于查看,不能用于日后的数据恢复

#mysqlbinlog mybinlog.000002  --start-position=100 > /tmp/1.sql # /tmp/1.sql可用于日后的数据恢复
 

如果查看过程报错
unknown variable 'default-character-set=utf8mb4' 
原因是mysql5.6中,mysqlbinlog这个工具无法识别binlog中的配置中的default-character-set=utf8mb4这个配置项目。 
两个方法可以解决这个问题
一是在MySQL的配置/etc/my.cnf中
将default-character-set=utf8mb4 修改为 character-set-server = utf8mb4,但是这需要重启MySQL服务,如果你的MySQL服务正在忙,那这样的代价会比较大。 
二是用mysqlbinlog --no-defaults mysql-bin.000001 命令打开

恢复数据

###恢复数据库的时候关闭binlog的记录功能
set sql_log_bin=1;  #在数据库内临时关闭,退出当前终端失效且设置仅在当前终端有效
set sql_log_bin=0; #恢复完成后再开启

示例:
#修改数据
begin;
update user set name="XXX" where name="egon2";
commit;
#发现自己修改错了
select * from user;
#回滚,回滚不了,已经提交了
rollback;
select * from user;
#一怒之下删表
drop table user;
 
#恢复数据:查看binlog数据的起始点与要恢复到的位置点,导出成SQL
mysqlbinlog mybinlog.000002 --stop-position=772 > /tmp/binlog.sql 
mysql -uroot -pEgon@123 < /tmp/binlog.sql    #将文件导入mysql(数据库外恢复)
或者
#source /tmp/binlog.sql   #在数据库内恢复数据

刷新与清除binlog

# 清除二进制日志原则

  • 在存储能力范围内,能多保留则多保留
  • 基于上一次全备前的可以选择删除

 
1) 删除所有binlog,相当于重置
reset master;
 
2) 删除指定binlog名之前的所有binlog(保留指定的binlog)
purge binary logs to 'mybinlog.00003'; -- mybinlog.00003之前的都删除掉
 
3)删除日期之前的日志:手动执行
PURGE {MASTER | BINARY} LOGS BEFORE 'date' --用于删除日期之前的日志,BEFORE变量的date自变量可以为'YYYY-MM-DD hh:mm:ss'格式
 
如:(MASTER 和BINARY 在这里都是等效的)
PURGE MASTER LOGS TO 'mybinlog.00003';
purge binary logs before '2021-07-13 19:11:00'; 
还可以做减法:如只保留3天的
PURGE BINARY LOGS BEFORE now() - INTERVAL 3 day;
 

4)删除日期之前的日志:修改配置参数,让mysql自动执行
删除7天前的binlog
#临时生效
SET GLOBAL expire_logs_days = 7; 
#永久生效
[root@db01 data]# vim /etc/my.cnf
[mysqld]
expire_logs_days = 7

三、备份与恢复

定义

为什么要备份
          硬件故障  软件故障  自然灾害  黑客攻击  误操作(占比最大)

备份什么
    数据
    二进制日志,InnoDB事务日志
    代码(存储过程、存储函数、触发器、事件调度器)
    服务器配置文件

备份的类型

###根据备份时数据库的运行状态

1)冷备:停库、停服务来备份
即当数据库进行备份时, 数据库不能进行读写操作, 即数据库要下线 
2)温备:不停库、不停服务来备份,会(锁表)阻止用户的写入   
即当数据库进行备份时, 数据库的读操作可以执行, 但是不能执行写操作 
3)热备(建议):不停库、不停服务来备份,也不会(锁表)阻止用户的写入
即当数据库进行备份时, 数据库的读写操作均不是受影响 


注意:Innodb全都支持;MyISAM不支持热备

###根据备份的内容

物理备份:直接将底层物理文件备份
逻辑备份:通过特定的工具从数据库中导出sql语句或者数据,可能会丢失数据精度

###根据备份的数据量

# 1、差异备份(Differential Backup)
每次备份时,都是基于第一次完全备份的内容,只备份有差异的数据(新增的、修改的、删除的), 
# 2、增量备份(Incremental Backup )
每次备份时,都是基于上一次备份的内容(注意是上一次,而不是第一次),只备份有差异的数据(新增的、修改的、删除的),所以增量备份的结果是一条链

# 1、全量备份的数据恢复
只需找出指定时间点的那一个备份文件即可,即只需要找到一个文件即可 
# 2、差异备份的数据恢复
需要先恢复第一次备份的结果,然后再恢复最近一次差异备份的结果,即需要找到两个文件 
# 3、增量备份的数据恢复
需要先恢复第一次备份的结果,然后再依次恢复每次增量备份,直到恢复到当前位置,即需要找到一条备份链 
综上,对比三种备份方案
1、占用空间:全量 > 差异 > 增量
2、恢复数据过程的复杂程度:增量 > 差异 > 全量

备份工具

备份策略及应用场景

  • 直接cp,tar复制数据库文件
  • mysqldump 全量 + 复制binlogs 增量
  • lvm2快照 全量 + 复制binlogs 增量
  • xtrabackup 全量+增量
    xtrabackup 全量 + binlogs 增量

1.如果数据量较小, 可以使用第一种方式,直接复制数据库文件,
2.如果数据量还行,可以使用第二种方式,先使用mysqldump对数据库进行完全备份,然后定期备份BINARY LOG达到增量备份的效果
3.如果数据量一般,而又不过分影响业务运行,可以使用第三种方式,使用lvm2的快照对数据文件进行备份,而后定期备份BINARY LOG达到增量备份的效果
4.如果数据量很大,而又不过分影响业务运行,可以使用第四种方式,使用xtrabackup进行完全备份后,定期使用xtrabackup进行增量备份或差异备份

备份实践

每天或者每周全备一次,全备之后那个位置点之前的binlog全都可以删除

cp

#1、向所有表施加读锁
FLUSH TABLES WITH READ LOCK;   
#2、备份数据文件
mkdir /egon_bak
cp -a /var/lib/mysql/* /egon_bak
# 数据丢失
rm -rf /var/lib/mysql/* 
# 恢复数据
cp -a /egon_bak/* /var/lib/mysql
# 重启服务
systemctl restart mysql

mysqldump

#==========语法
mysqldump  -h 服务器  -u用户名  -p密码  选项与参数 > 备份文件.sql
 
===选项与参数
1、-A/--all-databases             所有库
2、-B/--databases bbs db1 db2     多个数据库
3、db1                          数据库名
4、db1 t1 t2                 db1数据库的表t1、t2
5、-F                           备份的同时刷新binlog;做完全量刷新一个新的binlog文件进行备份方便查找
6、-R 备份存储过程和函数数据(如果开发写了函数和存储过程,就备,没写就不备)
7、--triggers 备份触发器数据(现在都是开发写触发器)
8、-E/--events 备份事件调度器
9、-d 仅表结构
10、-t 仅数据
11、--master-data=1  备份文件中 change master语句是没有注释的,默认为1
用于已经制作好了主从,现在想扩展一个从库的时候使用
如此备份,扩展添加从库时导入备份文件后
便不需要再加mater_pos了
change matser to
master_host='10.0.0.111'
master_user='rep'
master_password=123
master_log_pos=120
master_log_file='master-bin.000001' 
12、--master-data=2  备份文件中 change master语句是被注释的 
 
13、--lock-all-tables 备份过程中所有表从头锁到尾,简单粗暴
在mysqldump导出的整个过程中以read方式锁住数据库中所有表,类似 flush tables with read lock 的全局锁),这是一个全局读锁,只允许读不允许写,以此保证数据一致性。所以生产数据库的备份策略上,也很少使用该参数。该参数本身默认off,但使用该参数的话,也会自动将 --single-transaction 及 --lock-tables 参数置于 off 状态,他们是互斥的。
  
14、--single-transaction: 快照备份 (搭配--master-data可以做到热备)
保证各个表具有数据一致性快照。
指定 --single-transaction 参数,那么导出过程中只能保证每个表的数据一致性(利用多版本特性实现,目前只能针对InnoDB事务表)。

15、--lock-tables:如果是备份所有库,那么备份到某个库时只锁某个库,其他库可写,而--lock-all-tables是从始自终都全都锁定
 
 
#==========完整语句 
mysqldump -uroot -pEgon@123 -A -E -R --triggers --master-data=2 --single-transaction > /backup/full.sql
 
#====文件太大时可以压缩 gzip ,但是gzip不属于mysql独有的命令,可以利用管道
mysqldump -uroot -pEgon@123 -A -E -R --triggers --master-data=2 --single-transaction | gzip > /tmp/full$(date +%F).sql.gz
 
#====导出时压缩了,导入时需要解压,可以使用zcat命令,很方便
zcat /backup/full$(date +%F).sql.gz | mysql -uroot -p123

远程连一个账户用for循环一直进行写操作模拟数据库使用场景(复现热备,恢复数据)
### 增量恢复不一定是一次性恢复完的,中间可能会夹杂着一些删除语句,提前查询binlog确定好位置再恢复数据

===> 1、grep过滤 
===> 2、检查事件:依据End_log_pos的提示,来确定某一个事件的起始位置与结束位置
mysql> show binlog events in 'mybinlog.000001'; 
如果事件很多,可以分段查看
mysql> show binlog events in 'mybinlog.000001' limit 0,30; 
mysql> show binlog events in 'mybinlog.000001' limit 30,30; 
mysql> show binlog events in 'mybinlog.000001' limit 60,30;  
===> 3、利用mysqlbinlog命令
### 生产中很多库,只有一个库的表被删除,我不可能把所有的库都导出来筛选,因为那样子binlog内容很多,辨别复杂度高,我们可以利用 
[root@egon mysql]# mysqlbinlog -d db1 --start-position=123 --stop-position=154 mybinlog.000001 --base64-output=decode-rows -vvv | grep -v 'SET'
参数解释:
1)-d 参数接库名
mysqlbinlog -d database --base64-output=decode-rows -vvv mysql-bin.000002
2)--base64-output  显示模式
3)-vvv          显示详细信息

###备份
# 先打开binlog日志
# 在命令行执行下述命令,进行全量备份
[root@egon mysql]mysqldump -uroot -pEgon@123 -A -R --triggers --master-data=2 --single-transaction | gzip > /tmp/full.sql.gz 
# 全量备份完毕后的一段时间里,数据依然插入,写入了mybinlog.000001中
# 然后我们在命令行刷新binlog,产生了新的mybinlog.000002
[root@egon mysql]mysql -uroot -pEgon@123 -e "flush logs"
# 此时数据依然在插入,但都写入了最新的mybinlog.000002中,所以需要知道的是,增量的数据在mysqlbinlog.000001与mybinlog.000002中都有
###恢复
mysql> set sql_log_bin=0;
mysql> system zcat /tmp/full.sql.gz | mysql -uroot -pEgon@123
mysql> select * from db1.s1; -- 查看恢复到了id=28,剩下的去增量里恢复
 
# 在命令行导出mybinlog.000001中的增量,然后登录库进行恢复
查找位置,发现@1=29即第一列等于29,即id=29的下一个position是10275
mysql> show binlog events in 'mybinlog.000001';  
[root@egon mysql]# mysqlbinlog mybinlog.000001 --start-position=10038  --stop-position=11340 --base64-output=decode-rows -vvv | grep -v 'SET' | less
 
在命令行中执行导出
[root@egon mysql]# mysqlbinlog mybinlog.000001 --start-position=10275 > /tmp/1.sql
 
在库内执行导入,发现恢复到了39
mysql> source /tmp/1.sql  -- 最好是在库内恢复,因为sql_log_bin=0,导入操作不会记录
mysql> select * from db1.s1;
 
# 在命令行导出mybinlog.000002中的增量,然后登录库进行恢复
上面恢复到了id=39,我们接着找id=40的进行恢复,查找位置
发现@1=40的position是432
发现@1=55的position是6464
mysql> show binlog events in 'mybinlog.000002'; 
[root@egon mysql]# mysqlbinlog --base64-output=decode-rows -vvv mybinlog.000002|grep -v 'SET'|grep -C20 -w '@1=40'
[root@egon mysql]# mysqlbinlog --base64-output=decode-rows -vvv mybinlog.000002|grep -v 'SET'|grep -C20 -w '@1=55'
 
导出
[root@egon mysql]# mysqlbinlog mybinlog.000002 --start-position=432 --stop-position=6464> /tmp/2.sql
 
在库内执行导入,发现恢复到了55
mysql> source /tmp/2.sql  
mysql> select * from db1.s1;
 
# 开启binlog
mysql> SET sql_log_bin=ON; 

lvm2快照备份

###创建快照卷并备份
mysql> FLUSH TABLES WITH READ LOCK;     #锁定所有表
Query OK, 0 rows affected (0.00 sec)
 
[root@node1 lvm_data]# lvcreate -L 1G -s -n lv1_from_vg1_snap /dev/vg1/lv1   #创建快照卷
 
mysql> UNLOCK TABLES;  #解锁所有表
Query OK, 0 rows affected (0.00 sec)
 
[root@node1 lvm_data]# mkdir /snap1  #创建文件夹
[root@node1 lvm_data]# mount -o nouuid /dev/vg1/lv1_from_vg1_snap /snap1
 
[root@localhost snap1]# cd /snap1/
 
[root@localhost snap1]# tar cf /tmp/mysqlback.tar *  
 
[root@localhost snap1]# umount /snap1/ -l
[root@localhost snap1]# lvremove vg1/lv1_from_vg1_snap





###恢复   rm -rf /var/lib/mysql/*
tar xf /tmp/mysqlback.tar -C /var/lib/mysql/

xtrabackup

一种mysql数据库备份工具----速度快、热备、自动备份检验,配合inodb使用

mysql 5.7以下版本,可以采用percona xtrabackup 2.4版本 
mysql 8.0以上版本,可以采用percona xtrabackup 8.0版本,xtrabackup8.0也只支持mysql8.0以上的版本
比如,接触过一些金融行业,mysql版本还是多采用mysql 5.7,当然oracle官方对于mysql 8.0的开发支持力度日益加大,新功能新特性迭代不止。生产环境采用mysql 8.0的版本比例会日益增加。

安装

#第一种
# 安装yum仓库
yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm -y
 
# 安装XtraBackup命令
yum install percona-xtrabackup-24 -y




#第二种
#下载epel源
wget -O /etc/yum.repos.d/epel.repo  https://mirrors.aliyun.com/repo/epel-7.repo
 
#安装依赖
yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL
 
#下载Xtrabackup
wget https://downloads.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.23/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.23-1.el7.x86_64.rpm
 
# 安装
yum localinstall -y percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm

命令

xtrabackup      以前使用该命令
innobackupex    现在使用该命令
innobackupex是xtrabackup的前端配置工具,使用innobackupex备份时, 会调用xtrabackup备份所有的InnoDB表, 复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件, 同时还会备份触发器和数据库配置文件信息相关的文件, 这些文件会被保存至一个以时间命名的目录.

备份方式
1.对于非innodb表(比如myisam)是直接锁表cp数据文件,属于一种温备。 
2.对于innodb的表(支持事务),不锁表,cp数据页最终以数据文件方式保存下来,并且把redo和undo一并备走,属于热备方式。
3.备份时读取配置文件/etc/my.cnf

###全量

#1、创建备份目录,会把mysql的datadir中的内容备份到改目录中
mkdir /backup
#2、全备
#2.1 在本地执行下述命令,输入登录数据的本地账号与密码
#2.2 指定备份目录为/backup下的full目录
innobackupex --user=root --password=123 /backup/full 
#3、查看:默认会在备份目录下生成一个以时间戳命名的文件夹
[root@localhost ~]# cd /backup/full/
[root@localhost full]# ls
2021-07-16_16-09-47
[root@localhost full]# ls 2021-07-16_16-09-47/ #备份目录
。。。
[root@localhost full]# ls /var/lib/mysql # 数据目录
。。。 
# 4、去掉时间戳,让备份数据直接放在备份目录下
我们在写备份脚本和恢复脚本,恢复的时候必须指定上一次备份的目录,如果备份目录带着时间戳,该时间戳我们很难在脚本中确定,为了让脚本编写更加方便,我们可以使用选项--no-timestamp去掉时间戳,让备份内容直接放置于我们指定的目录下
[root@localhost full]# rm -rf 2021-07-16_17-45-53/
[root@localhost full]# innobackupex --user=root --password=123 --no-timestamp /backup/full 
# 补充:关于备份目录下新增的文件说明,可用cat命令查看
xtrabackup_checkpoints 存储系统版本号,增备的时候会用到
xtrabackup_info 存储UUID,数据库是由自己的UUID的,如果相同,做主从会有问题
xtrabackup_logfile 就是redo



###增量

#一 基于上一次备份进行增量,参数说明:
--incremental:开启增量备份功能
--incremental-basedir:上一次备份的路径 
#二 加上上一次命令
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/full/ /backup/xtra
 
#三 判断数据备份是否衔接
cat /backup/full/xtrabackup_checkpoints
    backup_type = full-backuped
    from_lsn = 0
    to_lsn = 1808756
    last_lsn = 1808756
    compact = 0
    recover_binlog_info = 0
    flushed_lsn = 1808756
 
cat /backup/xtra/xtrabackup_checkpoints 
    backup_type = incremental
    from_lsn = 1808756  # 值应该与全被的to_lsn一致
    to_lsn = 1808756
    last_lsn = 1808756
    compact = 0
    recover_binlog_info = 0
    flushed_lsn = 1808756

四、快速的导出和导入、数据迁移

select into outfile  导出
load data infile  导入
12G的数据导入约4分钟,导出约3分钟(十几个G需要十分钟左右)

快速导出

语法:
SELECT... INTO OUTFILE 导出文本文件
要想导出成功,需要设置安全目录才行
vim /etc/my.cnf
[mysqld]
secure-file-priv=/tmp
 
示例:
SELECT * FROM db1.t1
    INTO OUTFILE '/tmp/db1_t1.txt'
    FIELDS TERMINATED BY ','      -- 定义字段分隔符,不指定默认为空格
    OPTIONALLY ENCLOSED BY '"'    -- 定义字符串使用什么符号括起来
    LINES TERMINATED BY '\n';     -- 定义换行符

快速导入

(新表与旧表的表结构应该保持一致)

语法
LOAD DATA INFILE 导入的文本文件路径
 
示例
mysql> DELETE FROM student1;
mysql> create table new_t1(表结构与文件中数据保持一致);
mysql> LOAD DATA INFILE '/tmp/db1_t1.txt'
            INTO TABLE new_db.new_t1
            FIELDS TERMINATED BY ','
            OPTIONALLY ENCLOSED BY '"'
            LINES TERMINATED BY '\n';

导出其他格式

mysql 命令导出文本文件
示例:
# mysql -u root -pEgon123 -e 'select * from db1.t1' > /tmp/db1_t1.txt
# mysql -u root -pEgon123 --xml -e 'select * from db1.t1' > /tmp/db1_t1.xml    #给别人用
# xml  ----跨平台交互数据格式
# mysql -u root -pEgon123 --html -e 'select * from db1.t1' > /tmp/db1_t1.html   #给别人看

数据迁移

方案一:数据库导出,拷贝到新服务器,再导入
(数据迁移是因为业务瓶颈或项目改造等需要变动数据表结构的只能用此法)

#例如
(1)基于mysqldump(数据量小)
###在源主机执行下述命令,需要目标主机开启远程账号权限
mysqldump -h 迁移源IP -uroot -p123 --databases bbs | mysql -h 目标IP -uroot -p456 
(2)基于LOAD DATA INFILE(数据量大)
 
#优点:
会重建数据文件,减少数据文件的占用空间(释放undo段),兼容性最好(版本兼容),导出导入很少发生问题,需求灵活 
#缺点:
导入导出都需要很长的时间,并且导出后的文件还要经过网络传输,也要占用一定的时间。

方案二:第三方迁移工具

#例如
使用【MySQL GUI Tools】中的 MySQLMigrationTool。
 
#优点:
设置完成后传输无人值守,自动完成 
#缺点:
1、不够灵活,设置繁琐
2、传输时间长,
3、传输中网络出现异常,不能及时的被发现,并且会一直停留在数据传输的状态不能被停止,如不仔细观察不会被发现异常。
4、异常后很难从异常的位置继续传输。

方案三:数据文件和库表结构文件直接拷贝到新服务器,挂载到同样配置的mysql服务下

优点:
时间占用最短,文件可断点传输,操作步骤少。 
缺点:
新旧服务器中MySQL版本及配置必须相同,可能引起未知问题。

1、保证Mysql版本一致,安装配置基本一致(注意:这里的数据文件和库表结构文件都指定在同一目录data下)
2、停止两边的Mysql服务(A服务器--迁移-->B服务器)
3、删除B服务器Mysql的data目录下所有文件
4、拷贝A服务器Mysql的data目录下除了ib_logfile和.err之外的文件到B服务器data下
5、启动B服务器的Mysql服务,检测是否发生异常

五、Mysql主从

定义

将主服务器的binlog日志复制到从服务器上执行一遍,达到主从数据的一致状态,称之为主从复制。

作用

为什么要做主从

  1. 为实现数据库服务器的负载均衡/读写分离做铺垫,提升访问速度
  2. 通过复制实现数据的异地备份,保障数据安全
  3. 提高数据库系统的可用性
    从库临时取代主库,但只用来读(要求高安全性的场景)
    从库永久取代主库,负责读、写(新旧服务器数据的安全策略应相同)

补充:读写分离

#1、什么是读写分离
有了主从保持数据一致作为大前提,我们便可以可以分离读写操作,其中Master负责写操作的负载,也就是说一切写的操作都在Master上进行,而读的操作则分摊到Slave上进行。
#2、读写分离的作用
先说答案:读写分离可以大大提高读取的效率。 
读/写的比例大概在 10:1左右 ,也就是说写操作非常少,大量的数据操作是集中在读的操作
写操作涉及到锁的问题,不管是行锁还是表锁还是块锁,都是比较降低系统执行效率的事情。
 
#3、具体做法
方案一:
就是主库写,从库读 
方案二:
主库负责写,还有部分读,从库只负责读,而且是读操作的主力
 
即当主服务器比较忙时,部分查询请求会自动发送到从服务器中,以降低主服务器的工作负荷。
但哪些重要的数据还是用主库来读交给开发负责

主从复制的原理

master主  slave从

限制:客户在master上的写请求是并发的,但dump线程的提交(同步操作)是串行的

整体复制步骤:

  1. master将改变记录到binlog中
  2. slave的io线程将master的binlog拷贝到它的中继日志relaylog
  3. slave的sql线程解析中继日志的事件并执行,保持与主库一致

详解:

# 从库准备
(1)从库change master to 时,ip port user password binlog position写入到master.info进行记录
(2)从库 start slave 时,会启动IO线程和SQL线程
 
# 同步的过程
1.从库的IO线程,读取master.info信息,获取主库信息并连接主库
2.主库接收从库的链接请求后,会生成一个准备binlog DUMP的线程,来响应从库
3.主库一旦有新的日志生成,会发送“信号”给主库的binlog dump线程,然后binlog dump线程会读取binlog日志的更新
4.TP(传送)给从从库的IO线程
5.IO线程将收到的日志存储到了TCP/IP 缓存
6.写入TCP/IP缓存后,立即返回ACK给主库 ,此时主库工作完成
7.IO线程更新master.info文件binlog 文件名和postion
8.IO线程将缓存中的数据,存储到relay-log日志文件,此时io线程工作完成
9.从库SQL线程读取relay-log.info文件,获取到上次执行到的relay-log的位置,作为起点
10.从库SQL线程基于从步骤9中获取到的起点,去中继日志relay-log.000001获取后续操作,在从库回放relay-log
11.SQL线程回放完成之后,会更新relay-log.info文件,把当前操作的位置记入,作为下一次操作的起点。
12. relay-log会有自动清理的功能。

主从复制的日志格式

等于binlog日志(二进制日志)的日志格式

主从复制的方式

双主---互相开启binlog与relaylog

异步复制

客户端线程提交一个写操作,写入主库的binlog日志后就立即返回,不等从库完成同步操作,主库的dump线程会监测binlog日志的变量然后主动将更新推送给从库。

  • 客户端的写请求是并发的,但dump线程的提交(同步操作)是串行的且数据量一大或者网络延迟,会造成延迟现象;也会存在数据丢失的问题,主库写入binlog后数据还没推送到从库就丢了,但返回给客户端的是操作成功
  • Mysql主从复制默认为异步复制
  • 一次写操作刷入一个日志
  • 适用于追求效率高的场景

部署异步复制

前提:主从数据库版本一致

主库停服时制作主从(无读写操作) 

rm -rf /var/lib/mysql/*  #在测试环境下做实验时初始化数据库

主库192.168.15.101:

创建一个用于复制的账号并赋予replication slave权限

mysql> grant replication slave on *.* to 'egon'@'%' identified by '123';
mysql> flush privileges;

修改主库配置文件,开启主库binlog,并设置server-id

[mysqld]
# 节点ID,确保服务器的唯一性
server-id = 1        
 
#开启mysql的binlog日志功能
log-bin = mysql-bin
#控制数据库的binlog刷到磁盘上去 , 0 不控制,性能最好,1每次事物提交都会刷到日志文件中,性能最差,最安全
sync_binlog = 1     
#binlog日志格式
binlog_format = row   
#binlog过期清理时间
expire_logs_days = 7
#binlog每个日志文件大小
max_binlog_size = 100m
#binlog缓存大小
binlog_cache_size = 4m   
#最大binlog缓存大小
max_binlog_cache_size= 512m         
 
#不生成日志文件的数据库,多个忽略数据库可以用逗号拼接,或者 复制黏贴下述配置项,写多行
binlog-ignore-db=mysql 
 
# 表中自增字段每次的偏移量
auto-increment-offset = 1 
# 表中自增字段每次的自增量
auto-increment-increment = 1  
#跳过从库错误
slave-skip-errors = all 

重启主库

systemctl restart mysql

备份主库,备份时锁表保证备份一致 

mysqldump -uroot -pEgon@123 -A -E -R --triggers --triggers --master-data=2 --single-transaction > /tmp/all.sql

发送给从库

scp /tmp/all.sql root@192.168.15.100:/tmp

从库:192.168.15.100

测试复制账号并导入初始数据

mysql -uegon -p123 -h 192.168.15.101
mysql -uroot -pEgon@123 < /tmp/all.sql 

修改从库配置文件增加server-id(唯一)并重启从库

[mysqld]
server-id = 2
 
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
 
# 从库也可以开启binlog,但通常关闭
# log-bin=mysql-bin

systemctl restart mysqld

去主库查看binlog日志名与位置在从库进行配置并开启slave线程

#主库
show master status;

#从库
[root@slave1 ~]# mysql -uroot -pEgon@123 # 登录然后执行 
change master to
master_host='192.168.15.101',  -- 库服务器的IP
master_port=3306,              -- 主库端口
master_user='egon', -- 主库用于复制的用户
master_password='123', -- 密码
master_log_file='mysql-bin.000001', -- 主库日志名
master_log_pos=120; -- 主库日志偏移量,即从何处开始复制

#启动slave线程并检查
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

show slave status\G
##io线程与sql线程为yes状态即可

        

        

  

主库运行时制作主从

先做全量备份,备份完成后进行打点记录,从库配置完成后在进行增量备份与主库同步的时候从做完全量备份时打点的位置开始同步数据,防止中间一段时间主库写入数据的丢失

打点备份:记录做完全量备份的时候binlog记录的位置position

1.准备纯净的从库环境
主库:192.168.15.101
从库:192.168.15.100
 
2.修改主库配置文件(略)
3.重启主库(略)
4.主库创建账号(略)
5.模拟主库运行,有数据写入、
for i in `seq 1 1000000`
do 
    mysql -uroot -p123 -e "insert db1.t1 values($i)";
    sleep 1;
done
 
6.主库全备数据
#不打点备份(no)
mysqldump -uroot -p123 -A -R --triggers > /tmp/all.sql
#打点备份(yes)
mysqldump -uroot -p123 -A -R --triggers --master-data=2 --single-transaction > /tmp/all.sql
 
7.将热备数据传达从库
scp /tmp/all.sql 192.168.15.100:/tmp
 
8.修改从库配置文件(略)
 
9.重启从库(略)
 
10.在从库导入全备数据(导入打点备份)

11.查看sql文件中的位置点(如果是打点备份的话)
该位置即主库刚刚做完全量备份时,主库binlog日志所处的位置
[root@egon ~]# head -50 /tmp/all.sql|grep 'MASTER_LOG_POS'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=129005;
 
12.从库配置同步
[root@slave1 ~]# mysql -uroot -pEgon@123 # 登录然后执行
change master to
master_host='192.168.15.101',
master_port=3306, 
master_user='egon',
master_password='123',
master_log_file='mysql-bin.000001', 
master_log_pos=129005; 
 
13.开启SQL线程和IO线程
    start slave;
14.查看主从状态
    show slave status;

半同步复制(Mysql5.5开始)

1、一个事务操作的完成需要记完两份日志,即主从的binlog是同步的
半同步复制,当主库每提交一个事务后,不会立即返回,而是等待其中一个从库接收到Binlog并成功写入Relay-log中才返回客户端,所以这样就保证了一个事务至少有两份日志,一份保存在主库的Binlog,另一份保存在其中一个从库的Relay-log中,从而保证了数据的安全性和一致性。
 
2、半同步即并非完全同步
从库的数据对于主库来说还是有延时的,这个延时就是从库sql线程执行Relay-log的时间。所以只能称为半同步。
 
3、半同步复制超时则会切换回异步复制,正常后则切回半同步复制
在半同步复制时,如果主库的一个事务提交成功了,在推送到从库的过程当中,从库宕机了或网络故障,导致一段时间内从库并没有接收到这个事务的Binlog,此时主库会等待一段时间(这个时间由rpl_semi_sync_master_timeout的毫秒数决定),如果这个时间过后还无法推送到从库,那MySQL会自动从半同步复制切换为异步复制先返回给用户操作成功的信息,当从库恢复正常连接到主库后,主库又会自动切换回半同步复制。

  • 一次写操作刷入两次日志  主库的binlog与从库的relaylog
  • 主从之间不存在数据丢失,问题出现在从库的sql线程读取上,sql运行过慢会出现延迟
  • 适用于对数据一致性要求高的场景,例如做负载均衡
  • 可靠性大于异步复制

部署半同步复制

通过使用插件实现,主从库使用的插件不一样

确认mysql服务器是否支持动态增加插件

mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)

主从分别安装插件

# 插件一般默认在MySQL安装目录/lib/plugin下,可以去查看一下是否存在
ls /usr/lib64/mysql/plugin/ | grep semisync
 
# 主库的插件是semisync_master.so,从库是semisync_slave.so
 
主库> install plugin rpl_semi_sync_master soname 'semisync_master.so';
 
从库> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
 
# 安装完成后,在plugin表(系统表)中查看一下
select * from mysql.plugin;

开启半同步复制

###主库
#启动插件
mysql> set global rpl_semi_sync_master_enabled=1;
#设置超时
mysql> set global rpl_semi_sync_master_timeout=30000;
 
#修改配置文件
[root@db01 ~]# vim /etc/my.cnf
#在[mysqld]标签下添加如下内容(不用重启库,因为上面已经开启了)
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000



###从库
#启动插件
mysql> set global rpl_semi_sync_slave_enabled=1;
 
#重启io线程使其生效
mysql> stop slave io_thread;
mysql> start slave io_thread;
 
#编辑配置文件(不需要重启数据库)
[root@mysql-db02 ~]# vim /etc/my.cnf
 
#在[mysqld]标签下添加如下内容
[mysqld]
rpl_semi_sync_slave_enabled =1

查看状态

mysql>show status like '%semi_sync';
 
在输出信息中,我们重点关注三个参数:
 
#ON表示半同步复制打开,OFF表示关闭
rpl_semi_sync_master_status  OFF/ON
 
#这个数字表示主库当前有几个事务说通过半同步复制到从库的
rpl_semi_sync_master_yes_tx   [number] 
 
#表示有几个事务不是通过半同步复制到从库的
rpl_semi_sync_master_no_tx   [number]      

全同步复制

(效率过低)----等11步完成后才回复给客户端确认消息

延迟从库

  • 我们说用延时从库可以做备份,主库执行删除的时候,从库还没有删除,可以把表数据拿出来恢复回去
  • 企业中一般会延时3-6小时
  • 延时从库是在SQL线程做的手脚,IO线程已经把数据放到relay-log里了.
    SQL线程在执行的时候,会延迟你设定的时间长度

配置

  1. 已经存在主从
    1.停止主从
        mysql> stop slave;
    2.设置延时为180秒
        mysql> CHANGE MASTER TO MASTER_DELAY = 180;
    3.开启主从
        mysql> start slave;
    4.查看状态
        mysql> show slave status \G
        SQL_Delay: 180
    5.主库创建数据,会看到从库值变化,创建的库没有创建
        SQL_Remaining_Delay: 170


     
  2. 主从还未建立
    1.修改主库,从库配置文件
        server_id
        开启binlog
     
    2.保证从库和主库的数据一致
     
    3.执行change语句
        change master to
        master_host='172.16.1.50',
        master_user='rep',
        master_password='123',
        master_log_file='mysql-bin.000001',
        master_log_pos=2752,
        master_delay=180;


     
  3. 延时从库的停止
    1.停止主从
    mysql> stop slave;
     
    2.设置延时为0
    mysql> CHANGE MASTER TO MASTER_DELAY = 0;
     
    3.开启主从
    mysql> start slave;
     
    #注:做延时从库只是为了备份,不提供服务

延时从库进行数据恢复

1、场景

总数据量级500G,正常备份去恢复需要1.5-2小时
1)配置延时3600秒
mysql> CHANGE MASTER TO MASTER_DELAY = 3600; 
2)主库
drop database db; 
3)怎么利用延时从库,恢复数据?

2、环境准备

1.进行每日的全备
mysqldump -uroot -p123 -A -R --triggers --master-data=2 –single-transaction > /backup/full.sql 
2.调整延时从库延时时间为60分钟
    stop slave;
    CHANGE MASTER TO MASTER_DELAY = 3600;
    start slave; 
3.主库写入新数据
    create database yanshi;
    use yanshi;
    create table yanshi(id int);
    insert into yanshi values(1),(2),(3),(4);
 
    create database yanshi2;
    use yanshi2;
    create table yanshi2(id int);
    insert into yanshi2 values(1),(2),(3),(4);

3、模拟删除数据

    删除一个库,可以是之前的,也可以是刚创建的
    #因为刚我们看了,只要我执行了,从库已经写到了relay-log,跟我数据库里的数据关系不大
    drop database world;

4、恢复

1.停止从库sql线程
    stop slave sql_thread;
2.查看状态
    show slave status;
3.备份从库数据
    mysqldump -uroot -p123 -B world > /backup/congku.sql
4.截取一下relay-log
    1)确认起点,查看relay-log.info即可
        [root@db02 data]# cat relay-log.info
        ./db02-relay-bin.000005
        283
    2)确认终点,找到drop语句之前
        [root@db02 data]# mysqlbinlog --base64-output=decode-rows -vvv db02-relay-bin.000005
 
    3)截取数据
        [root@db02 data]# mysqlbinlog --start-position=283 --stop-position=1112 db02-relay-bin.000005 > /tmp/yanshi.sql
5.将从库全备的数据与relaylog截取数据拷贝到主库
    scp /tmp/yanshi.sql 172.16.1.51:/tmp/
    scp /backup/congku.sql 172.16.1.51:/tmp/
6.将数据导入主库
    #导入前不要停掉binlog,
    mysql < /tmp/yanshi.sql
    mysql < /tmp/congku.sql
7.开启从库的sql线程
    start slave sql_thread;
 
#主库那边执行到删除的时候没关系,因为还有创建的部分,他会再次把数据创建回来

过滤复制

需求:数据库同步时只同步指定的部分信息,不适用于做负载均衡

黑名单

不记录黑名单列出的库的二进制日志
 
#参数
replicate-ignore-db=test     #先库后表,表依赖于库
replicate-ignore-table=test.t1
replicate-wild-ignore-table=test.t%  支持通配符,t开头的表
 
注意:
replicate-ignore-table依赖参数replicate-ignore-db
即如果想忽略某个库下的某张表,需要一起配置    
replicate-ignore-db=test
replicate-ignore-table=test.t1

白名单

只执行白名单中列出的库或者表的中继日志
 
#参数:
replicate-do-db=test
replicate-do-table=test.t1
replicate-wild-do-table=test.t%
 
注意:
replicate-do-table依赖参数replicate-do-db
即如果想只接收某个库下的某张表,需要一起配置
replicate-do-db=test
replicate-do-table=test.t1

补充:

# 1、黑白名单对主库的影响是:是否记录binlog日志
在主库上设置白名单:只记录白名单设置的库或者表、相关的SQL语句到binlog中
在主库上设置黑名单:不记录黑名单设置的库或者表、相关的SQL语句到binlog中
 
# 2、黑白名单对从库的影响是:sql线程是否执行io线程拿到的binlog
IO线程一定会拿到所有的binlog,但
 
如果在从库上设置白名单:SQL线程只执行白名单设置的库或者表相关的SQL语句
如果在从库上设置黑名单:SQL线程不执行黑名单设置的库或者表相关的SQL语句

配置测试

###先做好一主两从
# 如果查看从库show slave status\G报错
A slave with the same server_uuid/server_id as this slave has connected to the master;
# 解决方案如下
如果server_id相同,请修改/etc/my.cnf中server_id的配置
 
如果server_uuid相同,请删除auto.cnf文件(auto.cnf文件在/etc/my.cnf中datadir配置的目录下),然后重启数据库,数据库会重新生成server_uuid和auto.cnf文件



#从库1
[root@db02 ~]# vim /etc/my.cnf
[mysqld]
replicate-do-db=big_egon
 
[root@db02 ~]# systemctl restart mysql
 
#查看主从状态
show slave status;



#从库2
[root@db03 ~]# vim /etc/my.cnf
[mysqld]
replicate-wild-do-table=big_egon.t%
replicate-do-db=small_egon
replicate-do-table=small_egon.t1
 
[root@db03 ~]# systemctl restart mysql
 
#查看主从状态
show slave status;




#主库创建表测试
create database big_egon;
create database small_egon;
 
use big_egon;
create table t1(id int);  -- 表名以t开头
create table t2(id int);  -- 表名以t开头
create table x3(id int);
 
use small_egon;
create table t1(id int);
create table t2(id int);
create table t3(id int);



#从库查看表
从库1上只能看到big_egon库下的所有表:t1、t2、x3
 
从库2上只能看到
    big_egon库下t开头的那两张表,看不到表x3
    small_egon库下的t1表

主从复制架构

  1.    主备架构,只有主库提供读写服务,备库仅留做备用     
    1、高可用分析:高可用,主库挂了,keepalive(只是一种工具)会自动切换到备库。这个过程对业务层是透明的,无需修改代码或配置
    2、高性能分析:读写都操作主库,很容易产生瓶颈。大部分联网应用读多写少,读会先成为瓶颈,进而影响写性能。另外,备库只是单纯的备份,资源利用率50%,这点方案二可解决。
    3、一致性分析:读写都操作主库,不存在数据一致性问题。
    4、扩展性分析:无法通过加从库来扩展读性能,进而提高整体性能。
    5、可落地分析:两点影响落地使用。第一,性能一般,这点可以通过建立高效的索引和引入缓存来增加读性能,进而提高性能。这也是通用的方案。第二,扩展性差,这点可以通过分库分表来扩展。

     
  2. 双主架构,两个主库同时提供服务,负载均衡       
    1、高可用分析:高可用,一个主库挂了,不影响另一台主库提供服务。这个过程对业务层是透明的,无需修改代码或配置。
    2、高性能分析:读写性能相比于方案一都得到提升,提升一倍。
    3、一致性分析:存在数据一致性问题。请看,一致性解决方案
    4、扩展性分析:当然可以扩展成三主循环,但不建议(会多一层数据同步,这样同步的时间会更长)。如果非得在数据库架构层面扩展的话,扩展为方案四。
    5、可落地分析:两点影响落地使用。第一,数据致性问题,一致性解决方案可解决问题。第二,主键冲突问题,ID统一地由分布式ID生成服务来生成可解决问题。

     
  3. 主从架构,一主多从,读写分离   
    1、高可用分析:主库单点,从库高可用。一旦主库挂了,写服务也就无法提供。
    2、高性能分析:大部分互联网应用读多写少,读会先成为瓶颈,进而影响整体性能。读的性能提高了,整体性能也提高了。另外,主库可以不用索引,线上从库和线下从库也可以建立不同的索引(线上从库如果有多个还是要建立相同的索引,不然得不偿失;线下从库是平时开发人员排查线上问题时查的库,可以建更多的索引)
    3、一致性分析:存在数据一致性问题。请看,一致性解决方案。
    4、扩展性分析:可以通过加从库来扩展读性能,进而提高整体性能。(带来的问题是,从库越多需要从主库拉取binlog日志的端就越多,进而影响主库的性能,并且数据同步完成的时间也会更长)
    5、可落地分析:两点影响落地使用。第一,数据一致性问题,一致性解决方案可解决问题。第二,主库单点问题。         

     
  4. 级联复制架构                 
    级联复制----扩大从库的规模,让主库的从库充当下一级从库的主库,减小了主库的压力

    但它的缺点就是Binlog日志要经过两次复制才能到达从库,增加了复制的延时。
    我们可以通过在二级从库上应用Blackhol存储引擎(黑洞引擎)来解决这一问题,降低多级复制的延时。
    黑洞引擎”就是写入Blackhole表中数据并不会写到磁盘上,所以这个Blackhole表永远是个空表,对数据的插入/更新/删除操作仅在Binlog中记录,并复制到从库中去。

     
  5. 双主+双从架构
    1、高可用分析:高可用。
    2、高性能分析:高性能。
    3、一致性分析:存在数据一致性问题。请看,一致性解决方案
    4、扩展性分析:可以通过加从库来扩展读性能,进而提高整体性能。(带来的问题同方案二)
    5、可落地分析:同方案二,但数据同步又多了一层,数据延迟更严重。

一致性解决方案

只要进行数据同步,就会出现延时一致性的问题

硬件优化

1.采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。
 
2.存储用ssd或者盘阵或者san,提升随机写的性能。
 
3.主从间保证处在同一个交换机下面,并且是万兆环境。
 
总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。

文件系统优化

master端修改linux、Unix文件系统中文件的etime属性,由于每当读文件时OS都会将读取操作发生的时间回写到磁盘上,对于读操作频繁的数据库文件来说这是没必要的,只会增加磁盘系统的负担影响I/O性能。可以通过设置文件系统的mount属性,组织操作系统写atime信息
    在linux上的操作为:
        打开/etc/fstab
        加上noatime参数/dev/sdb1 /data reiserfs noatime 1 2
        然后重新mount文件系统 #mount -oremount /data

MySQL参数优化

1、logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
 
2、sync_binlog在slave端设置为0或禁用slave端的binlog
 
3、slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit =2
 
对数据安全性较高,需要设置
sync_binlog=1
innodb_flush_log_at_trx_commit = 1 
而对于slave则不需要这么高的数据安全,完全可以设置为
sync_binlog=0或者关闭binlog
innodb_flush_log_at_trx_commit =0或2

主从都开启GTID复制模式,使用MHA

MHA

1、支持binlogserver  专门负责同步主库的binlog的服务器
                             ----解决commit之后更新还没推送给从库主库就挂掉了

  1. 重启mysql重新同步
  2. 主库如果是物理层面的损坏,使用binlogserver对从库进行数据恢复                         

2、一主多从更新推给多台从服务器的先后一致性问题

          基于GTID解决(不用也可以,查谁的binlog最新即可)
          看谁身上的数据量大数据新就跟谁同步数据,(如果主库故障了)综合选举出一个新的主库,进行vip飘移

架构方面

1、强制读主----读写都走主库,不存在一致性问题

为了缓解主库的读压力,可以引入缓存。
但是有一点需要知道:如果缓存挂了,可能会产生雪崩现象,不过一般分布式缓存都是高可用的。
在本架构中,从库的作用是,主库一旦挂掉,vip则漂移到从库上,从库可以投入使用。

                             

2、选择读主

缓存数据库的数据过期超时时间的设置一定要大于数据库主从一致的时间----保证请求去数据库读数据的时候在从库上能读到从而减轻主库的压力

                

3、选择半同步复制

4、引入数据库中间件

六、企业环境介绍

  1. 开发环境
    开发开发完自己测试
     
  2. 测试环境
    1)性能测试
    2)功能测试
     
  3. 预发布环境(beta,内测不删档)
    (1)、只是一台服务器
     
    (2)、没有真实的流量
     
    (3)、连的是线上数据库
     
    疑问:如果有一个待上线需求,需要改动数据库表结构,怎么处理?
     
    先把预发布环境使用的数据库切换为测试环境使用的数据库
    然后有针对性的测试下数据库的变更是否会影响线上当前代码程序的运行,测试通过后再上线

     
  4. 灰度环境
    (1)、1台或多台线上主机
     
    (2)、链接的是线上数据库
     
    (3)、真实流量
     
    灰度发布,又称金丝雀发布。
    金丝雀发布这一术语源于煤矿工人把笼养的金丝雀带入矿井的传统。矿工通过金丝雀来了解矿井中一氧化碳的浓度,如果一氧化碳的浓度过高,金丝雀就会中毒,从而使矿工知道应该立刻撤离。
     
    灰度发布发生在预发布环境之后,生产环境之前。
    对应到软件开中,则是指在发布新的产品特性时通过少量的用户试点确认新特性没有问题,确保无误后推广到更大的用户使用群体。
     
    生产环境一般会部署在多台机器上,以防某台机器出现故障,这样其他机器可以继续运行,不影响用户使用。灰度发布会发布到其中的几台机器上,验证新功能是否正常。如果失败,只需回滚这几台机器即可。

     
  5. 沙盒环境
    沙盒环境又称测试环境和开发环境,是提供给开发者开发和测试用的环境。
    沙盒通常严格控制其中的程序所能访问的资源,比如,沙盒可以提供用后即回收的磁盘及内存空间。在沙盒中,网络访问、对真实系统的访问、对输入设备的读取通常被禁止或是严格限制。
     
    也就是说所谓的沙盒测试就是在产品未上线前在内部环境或网络下进行的测试,此时在正常的线上环境是无法看到或查询到该产品或项目的,只有产品在测试环境下无问题上传到生产环境之后,用户才能看到该产品或功能

     
  6. 生产环境
    除了生产和预发布其他的环境都是虚拟机测试用的
     
    测试环境有很多游戏,我就想一个从库同步一种游戏,还有合服,建新服,其实就是一个库或者一个表而已.

七、MHA高可用

支持binlogserver  专门负责同步主库的binlog的服务器

                                  ----解决commit之后更新还没推送给从库主库就挂掉了

  1. 重启mysql重新同步
  2. 主库如果是物理层面的损坏,使用binlogserver对从库进行数据恢复                         

一主多从更新推给多台从服务器的先后一致性问题

          基于GTID解决(不用也可以,查谁的binlog最新即可)
          看谁身上的数据量大数据新就跟谁同步数据,(如果主库故障了)综合选举出一个新的主库,进行vip飘移

MHA程序的组成

node数据节点
          相当于监控客户端,所有数据库机器都需要部署node

manager管理节点
Manager相当于服务端,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master(如果原主库恢复,只能当从库)

  • 通常单独部署在一台独立机器上管理多个 master/slave 集群(组),每个master/slave 集群称作一个 application,用来管理统筹整个集群
  • Manager应该尽量避免部署在主库上,否则主机一挂则全挂,不仅主库完蛋了负责自动迁移的Manager也完蛋了,也没人负责自动故障迁移了,导致架构不可用了。
  • 可以考虑部署在某一个slave上,此时这台主机挂掉了,只是挂了一个slave,以及Manager,如果此时你不是倒了霉,(主库也挂了),那还不至于架构不可用。但有一点需要注意的是:如果Manager部署在slave上,那么该slave就无法被升级为主库;

MHA自动故障切换的步骤

  1. 每隔3秒探测一次主库是否存活
    ping_interval 控制间隔时间; 
    ping_type 控制探测方式,SELECT(执行SELECT 1)和CONNECT(创建连接/断开连接)

     
  2. 如果发现故障,进行如下操作
    1、从其他node发起ssh连接,检查主库是否能够SSH上去; 
    2、从其他node发起mysql连接,检查MASTER库是否能够登陆;

     
  3. 如果所有node节点ssh连接、MySQL主库连接均失败,则开始故障转移
    1.找到数据最新的从库(通过对比relay-log,show slave status即可)
    2.将最新的从库上的新数据同步到其他从库
    3.提升一个从库为主库(一般情况提升数据最新的,二般情况提升我们指定的从库为主库)
    4.通过原来主库的binlog补全新的主库数据(丢失了使用binlogserver)
    5.其他从库以新的主库为主做主从复制

MHA优点

1、自动的故障检测与转移,通常在10-30秒以内;
2、MHA还提供在线主库切换的功能,能够安全地切换当前运行的主库到个新的主库中(通过将从库提升为主库),大概0.5-2秒内即可完成。
3、很好地解决了主库崩溃数据的一致性问题
4、不需要对当前的mysql环境做重大修改
5、不需要在现有的复制框架中添加额外的服务器,仅需要-个manager节点,而一个Manager能管理多套复制,所以能大大地节约服务器的数量;
6、性能优秀,可以工作在半同步和异步复制框架,支持gtid,当监控mysq状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。
7、只要replication支持的存储引擎都支持MHA,不会局限于innodb
8、对于一般的keepalived高可用,当vip在一台机器上的时候,另一台机器是闲置的,而MHA中并无闲置主机。

GTID主从复制

定义

        MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

GTID------为每个事务定制一个全局唯一的ID号,并且该ID是趋势递增的,以此我们便可以方便地顺序读取、不丢事务,是取binlog的一种方式。其实GTID就是一种很好的分布式ID实践方案,它满足分布ID的两个基本要求,
1)全局唯一性
2)趋势递增
 
由UUID+TID两部分组成
    UUID是数据库实例的标识符
    TID表示事务提交的数量,会随着事务的提交递增

  • 当 MySQL 执行一个事务时,在事务提交阶段生成 GTID。生成的 GTID 会被记录到二进制日志(binlog)中,与事务的其他信息(如 SQL 语句、数据修改等)一起存储。这保证了每个事务在其生命周期内都有一个唯一且固定的 GTID 与之关联,无论该事务在主从复制环境中如何传播。
  • 从库的 SQL 线程在应用relayog中继日志中的事务时,首先检查事务的 GTID。它会维护一个已应用 GTID 的集合(通常存储在 gtid_executed 表或文件中)。当读取到一个新事务的 GTID 时,SQL 线程会在这个集合中查找。如果 GTID 已存在,说明该事务已经应用过,SQL 线程会跳过这个事务;如果 GTID 不存在,SQL 线程会应用该事务,并将其 GTID 添加到已应用 GTID 集合中

优缺点

优点
1、一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次,强化了一致性
2、GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置,直接自动查找
3、GTID会开启多个SQL线程,每一个库,开启一个SQL线程
4、支持延时复制

缺点
1.不支持非事务引擎
2.不支持create table t1(...) select* from t2; 语句复制(主库直接报错)
          原理:(会生成两个sql,一个是DDL创建表SQL,一个是insert into插入数据的sql。
               由于DDL会导致自动提交,所以这个sql至少需要两个GTID,但是GTID模式下,只能给这个sql生成一个GTID)
3.不允许一个SQL同时更新一个事务引擎表和非事务引擎表
4.在一个复制组中,必须要求统一开启GTID或者是关闭GTID
5.开启GTID需要重启(5.7除外)
6.开启GTID后,就不再使用原来的传统复制方式
7.对于create temporary table 和 drop temporary table语句不支持
8.不支持sql_slave_skip_counter
9.mysqldump 备份起来很麻烦,需要额外加参数 -set-gtid=on

基于GTID的主从复制部署(一主多从)

  • 主库和从库都要开启binlog
  • 主库和从库server-id必须不同
  • 要有主从复制用户

实现

###主:mysql5.6  192.168.15.100
[mysqld]
。。。。。。。
 
server-id=100
binlog_format=row
log-bin=mysql-bin
skip-name-resolve # 跳过域名解析(非必须)
gtid-mode=on # 启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true #强制GTID的一致性
log-slave-updates=1 # slave更新是否记入日志(5.6必须的)
relay_log_purge = 0 # 关闭relay_log自动清除功能,保障故障时的数据一致



###从1 mysql5.6  192.168.15.101  只有server-id与主不同
[mysqld]
。。。。。。。
server-id=101
binlog_format=row
log-bin=mysql-bin
skip-name-resolve # 跳过域名解析(非必须)
gtid-mode=on # 启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true #强制GTID的一致性
log-slave-updates=1 # slave更新是否记入日志(5.6必须的)
relay_log_purge = 0 # 关闭relay_log自动清除功能,保障故障时的数据一致



###从2 192.168.15.102
[mysqld]
。。。。。。。
server-id=102
binlog_format=row
log-bin=mysql-bin
skip-name-resolve # 跳过域名解析(非必须)
gtid-mode=on # 启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true #强制GTID的一致性
log-slave-updates=1 # slave更新是否记入日志(5.6必须的)
relay_log_purge = 0 # 关闭relay_log自动清除功能,保障故障时的数据一致



###在主库创建复制账户
mysql> GRANT REPLICATION SLAVE ON *.* TO egon@'%' IDENTIFIED BY '123';
Query OK, 0 rows affected (0.00 sec)
 
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)




###两个从库开启复制
change master to 
    master_host='192.168.15.100',
    master_user='egon',
    master_password='123',
    MASTER_AUTO_POSITION=1;



###启动从库复制
start slave;
show slave status\G
show variables like '%gtid%';


测试主从,结束




###如需改为双主架构
# 找一台从库,假设为192.168.15.101,在该主机上创建账号
GRANT REPLICATION SLAVE ON *.* TO egon@'%' IDENTIFIED BY '123';
flush privileges;
 
# 在主库上执行下述操作,指向从库192.168.15.101(把主库当从库)
change master to 
    master_host='192.168.15.101',
    master_user='egon',
    master_password='123',
    MASTER_AUTO_POSITION=1;
 
# 开启主库的slave(把主库当从库)
start slave;

MHA的部署

1、配置环境

在一主两从的基础上,所有主从服务器开启binlog、relaylog,关闭relay_log_purge,并设置从库relaylog只读read_only=1,增加一台manager服务器管理(多个)MHA集群

  • 所有服务器设置主从复制用户(主库创建从库同步)
    GRANT REPLICATION SLAVE ON *.* TO egon@'%' IDENTIFIED BY '123';
    flush privileges;
  • 主库设置一个管理用户便于日后MHA的管理
    # 在主库上执行即可,从库会同步过去同时创建
    grant all on *.* to 'mhaadmin'@'%' identified by '666';
    flush privileges;

     
  • #1、在从库上进行操作
    #设置只读,不要添加配置文件,因为从库以后可能变成主库
    mysql> set global read_only=1;
     
    #2、在所有库上都进行操作
    #关闭MySQL自动清除relaylog的功能
    mysql> set global relay_log_purge = 0; 
    #编辑配置文件
    [root@mysql-db02 ~]# vim /etc/my.cnf
    [mysqld]
    #禁用自动删除relay log永久生效
    relay_log_purge = 0
     
  • ssh免密登录
    #创建秘钥对
    #正常创建 ssh-keygen 需要交互 按回车,用以下方法跳过交互
    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.15.200
    ssh-copy-id -i /root/.ssh/id_dsa.pub root@192.168.15.100
    ssh-copy-id -i /root/.ssh/id_dsa.pub root@192.168.15.101
    ssh-copy-id -i /root/.ssh/id_dsa.pub root@192.168.15.102
    #测试
    ssh root@192.168.13.200 hostname
    ssh root@192.168.13.100 hostname
    ssh root@192.168.13.101 hostname
    ssh root@192.168.13.102 hostname
    #如果认证慢的话可以尝试修改/etc/ssh/sshd.conf中的UseDNS=no
     
  • 安装软件包(所有机器)
    # 安装yum源
    wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
    rpm -ivh epel-release-latest-7.noarch.rpm
     
    # 安装MHA依赖的perl包
    yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager

    #先在所有机器安装node包
    wget https://qiniu.wsfnk.com/mha4mysql-node-0.58-0.el7.centos.noarch.rpm --no-check-certificate
    rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm

    #再去manager主机安装manager包(.200)
    wget https://qiniu.wsfnk.com/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm --no-check-certificate
    rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm

2、配置MHA Manager

#建立单个MHA集群管理目录
mkdir -p /service/mha/
mkdir /service/mha/app1

#修改配置
#vim /service/mha/app1.cnf
[server default]            
#日志存放路径
manager_log=/service/mha/manager.log
#定义工作目录位置
manager_workdir=/service/mha/app1
 
#设置ssh的登录用户名
ssh_user=root
#如果端口修改不是22的话,需要加参数,不建议改ssh端口
#否则后续如负责VIP漂移的perl脚本也都得改,很麻烦
ssh_port=22
 
#管理用户
#在配置文件中设置管理用户的账号可以让其进行如下操作
#例如选择新的主库后将选的从库的选项 gobal read_only=1只读设置为0
#stop slave
#chage master
user=mhaadmin
password=666
 
#复制用户
repl_user=egon  
repl_password=123
 
#检测主库心跳的间隔时间
ping_interval=1
 
[server1]
# 指定自己的binlog日志存放目录
master_binlog_dir=/var/lib/mysql
hostname=192.168.15.100
port=3306
 
[server2]
#暂时注释掉,先不使用
#candidate_master=1
#check_repl_delay=0
master_binlog_dir=/var/lib/mysql
hostname=192.168.15.101
port=3306
 
[server3]
master_binlog_dir=/var/lib/mysql
hostname=192.168.15.102
port=3306
 
# 1、设置了以下两个参数,则该从库成为候选主库,优先级最高
# 不管怎样都切到优先级高的主机,一般在主机性能差异的时候用         
candidate_master=1
# 不管优先级高的备选库,数据延时多久都要往那切
check_repl_delay=0
 


# 2、上述两个参数详解如下:
# 设置参数candidate_master=1后,则判断该主机为为候选master,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave。
 
# 默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master


 
# 3、应该为什么节点设置这俩参数,从而把该节点的优先级调高
# (1)、多地多中心,设置本地节点为高权重
# (2)、在有半同步复制的环境中,设置半同步复制节点为高权重
# (3)、你觉着哪个机器适合做主节点,配置较高的 、性能较好的

3、检测MHA配置

#测试免密连接
1.使用mha命令检测ssh免密登录
masterha_check_ssh --conf=/service/mha/app1.cnf

#    ALL SSH ... successfilly 表示ok了
 


2.使用mha命令检测主从状态
masterha_check_repl --conf=/service/mha/app1.cnf

#    ... Health is OK
 #如果出现问题,可能是反向解析问题,配置文件加上
    skip-name-resolve
#还有可能是主从状态,mha用户密码的情况

4、启动与测试
nohup masterha_manager --conf=/service/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /service/mha/manager.log 2>&1 &
 
命令参数:
--remove_dead_master_conf       该参数代表当发生主从切换后,宕机库的配置信息将会从配置文件中移除。
--manger_log                    日志存放位置
--ignore_last_failover          在缺省情况下,如果MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover,之所以这样限制是为了避免ping-pong效应。该参数代表忽略上次MHA触发切换产生的文件,默认情况下,MHA发生切换后会在日志目录,也就是上面设置的manager_workdir目录中产生app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为--ignore_last_failover。
 

#MHA的安全机制:(防止出现乒乓效应)
    1.完成一次切换后,会生成一个锁文件在工作目录中
    2.下次切换之前,会检测锁文件是否存在
    3.如果锁文件存在,8个小时之内不允许第二次切换

5、测试自动切换与恢复

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

临床决策支持系统的提示工程优化路径深度解析

引言 随着人工智能技术在医疗领域的迅猛发展,临床决策支持系统(CDSS)正经历从传统规则引擎向智能提示工程的范式转变。在这一背景下,如何构建既符合循证医学原则又能适应个体化医疗需求的CDSS成为医学人工智能领域的核心挑战。本报告深入剖析了临床决策支持系统中提示工程的…

苹果新一代车载系统CarPlay Ultra来袭,全屏接管+ChatGPT助力,智能驾驶要“起飞”

AITOP100获悉&#xff0c;苹果又搞出大动作啦&#xff01;正式推出了新一代车载系统——CarPlay Ultra。这次&#xff0c;苹果可是下了狠功夫&#xff0c;把iPhone和汽车的所有显示屏深度整合到了一起&#xff0c;还首次把ChatGPT引入到了驾驶体验当中。这系统可不简单&#xf…

无线信道的噪声与干扰

目录 1. 无线信道(wireless channel)与电磁波 2.1 电磁波的传输(无线信道传输) 2.2 视线(line of sight)传播与天线高度 2. 信道的数学模型 2.1 调制信道模型 2.1.1 加性噪声/加性干扰 2.1.2 乘性噪声/乘性干扰 2.1.3 随参信道/恒参信道 2.2 编码信道模型 2.3 小结 …

MySQL 8.0 OCP 1Z0-908 101-110题

Q101.which two queries are examples of successful SQL injection attacks? A.SELECT id, name FROM backup_before WHERE name‘; DROP TABLE injection; --’; B. SELECT id, name FROM user WHERE id23 oR id32 OR 11; C. SELECT id, name FROM user WHERE user.id (SEL…

BBR 的 buffer 动力学观感

这周很忙&#xff0c;今天还加了一天班&#xff0c;但还是抽空实现了五一在安徽泾县山区喝着一壶酒写的 BBR ProbeRTT 的想法&#xff0c;没多少行代码&#xff0c;它真就消除了带宽锯齿&#xff0c;皮了个鞋&#x1f45e;&#xff0c;昨天我还在群里说了今天再说说 BBR 的&…

Spring之Bean的初始化 Bean的生命周期 全站式解析

目录 导图 步骤 第一步 实例化 第二步 属性赋值 第三步 初始化 aware 接口 BeanPostProcessor 接口 InitializingBean 和 init-method 第四步使用 第五步使用后销毁 描述一下 Bean 的 生命周期 导图 步骤 总体上可以分为五步 首先是 Bean 的实例化Bean 在进行实例…

FreeCAD源码分析: Transaction实现原理

本文阐述FreeCAD中Transaction的实现原理。 注1&#xff1a;限于研究水平&#xff0c;分析难免不当&#xff0c;欢迎批评指正。 注2&#xff1a;文章内容会不定期更新。 一、概念 Ref. from What is a Transaction? A transaction is a group of operations that have the f…

flutter缓存网络视频到本地,可离线观看

记录一下解决问题的过程&#xff0c;希望自己以后可以参考看看&#xff0c;解决更多的问题。 需求&#xff1a;flutter 缓存网络视频文件&#xff0c;可离线观看。 解决&#xff1a; 1&#xff0c;flutter APP视频播放组件调整&#xff1b; 2&#xff0c;找到视频播放组件&a…

Kotlin 中 infix 关键字的原理和使用场景

在 Kotlin 中&#xff0c;使用 infix 关键字修饰的函数称为中缀函数&#xff0c;使用是可以省略 . 和 ()&#xff0c;允许以更自然&#xff08;类似自然语言&#xff09;的语法调用函数&#xff0c;这种特性可以使代码更具可读性。 1 infix 的原理 中缀函数必须满足以下条件&…

c++从入门到精通(五)--异常处理,命名空间,多继承与虚继承

异常处理 栈展开过程&#xff1a; 栈展开过程沿着嵌套函数的调用链不断查找&#xff0c;直到找到了与异常匹配的catch子句为止&#xff1b;也可能一直没找到匹配的catch&#xff0c;则退出主函数后查找过程终止。栈展开过程中的对象被自动销毁。 在栈展开的过程中&#xff0c…

gcc/g++常用参数

1.介绍 gcc用于编译c语言&#xff0c;g用于编译c 源代码生成可执行文件过程&#xff0c;预处理-编译-汇编-链接。https://zhuanlan.zhihu.com/p/476697014 2.常用参数说明 2.1编译过程控制 参数作用-oOutput&#xff0c;指定输出名字-cCompile&#xff0c;编译源文件生成对…

nginx配置之负载均衡

版权声明&#xff1a;原创作品&#xff0c;请勿转载&#xff01; 1.实验环境准备 准备3台linux服务器&#xff08;ubuntu和centos均可&#xff0c;本文使用centos7.9&#xff09;&#xff0c;两台web和一台负载均衡服务器&#xff0c;均安装nginx服务 主机名IP软件lb0110.0.0…

去年开发一款鸿蒙Next Os的window工具箱

持拖载多个鸿蒙应用 批量签名安装 运行 http://dl.lozn.top/lozn/HarmonySignAndFileManagerTool_2024-11-26.zip 同类型安卓工具箱以及其他软件下载地址汇总 http://dl.lozn.top/lozn/ 怎么个玩法呢&#xff0c;比如要启动某app, 拖载识别到包名 点启动他能主动读取包名 然后…

uniapp|实现获取手机摄像头权限,调用相机拍照实现人脸识别相似度对比,拍照保存至相册,多端兼容(APP/微信小程序)

基于uniapp以及微信小程序实现移动端人脸识别相似度对比,实现摄像头、相册权限获取、相机模块交互、第三方识别集成等功能,附完整代码。 目录 核心功能实现流程摄像头与相册权限申请权限拒绝后的引导策略摄像头调用拍照事件处理人脸识别集成图片预处理(Base64编码/压缩)调用…

JavaScript【7】BOM模型

1.概述&#xff1a; BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09;是 JavaScript 中的一个重要概念&#xff0c;它提供了一系列对象来访问和操作浏览器的功能和信息。与 DOM&#xff08;Document Object Model&#xff09;主要关注文档结构不同&…

[强化学习的数学原理—赵世钰老师]学习笔记02-贝尔曼方程

本人为强化学习小白&#xff0c;为了在后续科研的过程中能够较好的结合强化学习来做相关研究&#xff0c;特意买了西湖大学赵世钰老师撰写的《强化学习数学原理》中文版这本书&#xff0c;并结合赵老师的讲解视频来学习和更深刻的理解强化学习相关概念&#xff0c;知识和算法技…

深入理解构造函数,析构函数

目录 1.引言 2.构造函数 1.概念 2.特性 3.析构函数 1.概念 2.特性 1.引言 如果一个类中什么都没有&#xff0c;叫作空类. class A {}; 那么我们这个类中真的是什么都没有吗?其实不是,如果我们类当中上面都不写.编译器会生成6个默认的成员函数。 默认成员函数:用户没有显…

Day 16

目录 1.JZ79 判断是不是平衡二叉树1.1 解析1.2 代码 2.DP10 最大子矩阵2.1 解析2.2 代码 1.JZ79 判断是不是平衡二叉树 JZ79 判断是不是平衡二叉树 dfs 1.1 解析 1.2 代码 /*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(in…

摄影构图小节

1、三分构图法 三分构图法即将画面横竖各分为三份&#xff0c;即九宫格形式。 将画面用两条竖线和两条横线分割&#xff0c;就如同是书写中文的【井】字。这样就可以得到4个交叉点&#xff0c;然后再将需要表现的重点放置在4个交叉点中的一个附近即可。 拍摄自然风光时&#xf…

DAY 28 类的定义和方法

知识点回顾&#xff1a; 类的定义pass占位语句类的初始化方法类的普通方法类的继承&#xff1a;属性的继承、方法的继承 比如def、class这些定义的关键词后&#xff0c;必须有一个有占据缩进位置的代码块。 还有下面这些依赖缩进的语句&#xff0c;都可以用pass语句来占位 x 1…