##================================================================##mysql
需求场景:sql
因为MySQL没有相似于SQL SERVER那样的系统表来存放备份记录,且大规模的MySQL服务器须要集中管理和查看。数据库
服务器出现性能问题或复制延迟时,须要先判断是否由数据备份引发。服务器
##================================================================##性能
初版优化
按照需求,考虑到须要记录的备份信息有备份服务器信息、备份开始结束时间、备份是否成功等消息,因而设计出初版表:spa
create table full_backup_log ( id bigint auto_increment primary key, ## 自增主键,业务无关 host_ip varchar(50), ## 备份机IP host_port int, ## 备份机端口 backup_type varchar(50), ## 备份类型,mysqldump和xtrabackup start_time datetime, ## 备份开始时间 end_time datetime, ## 备份结束时间 is_success int, ## 备份是否成功 backup_message varchar(5000), ## 备份消息 check_time datetime ##写入或更新记录的时间 );
##================================================================##设计
第二版日志
将backup_message弄得比较大, 主要是先把备份过程当中的一些信息写进去,但仔细想一想,该表不能很好地记录备份过程当中的每一步,将全部信息放入到backup_message列中不利于查看,因而新增一个详细信息表:code
create table full_backup_log_detail ( id bigint auto_increment primary key, ## 自增主键,业务无关 full_backup_log_id bigint, ##关联full_backup_log表主键 host_ip varchar(50), ## 备份机IP host_port int, ## 备份机端口 backup_type varchar(50), ## 备份类型,mysqldump和xtrabackup backup_message varchar(5000), ## 备份消息 check_time datetime ##写入或更新记录的时间 );
虽然full_backup_log表中存放有备份机和备份类型数据,能够经过full_backup_log_id关联来获取到,可是考虑full_backup_log_detail表数据数据日志性数据,写入后不会发生变化,所以经过冗余来减小关联,仅查询full_backup_log_detail便可看某台服务器的备份详情。
##================================================================##
第三版
一般DBA关心每一个数据库最后一次备份成功时间,而表full_backup_log中存有is_success字段用来标识备份成功,能够经过如下SQL来获取:
select t1.* from full_backup_log as t1 inner join ( select host_ip,host_port,max(id) as max_id from full_backup_log where is_success=1 group by host_ip,host_port ) as t2 on t1.id=t2.max_id
若是full_backup_log表数据量较大时,好比存放几千个实例的几年数据,表中数据几百万上千万时,上面查询即便有合适索引也不能高效执行。
因为DBA并不关心早前数据,能够经过数据结转来实现,但若是偶尔查询早前数据则须要当前表和历史表进行UNION,程序实现上还得判断数据是否结转,因而新增一表来存放最后一次成功备份记录:
## full_backup_info用来存放备份机最后一次成功备份的记录 create table full_backup_info ( id bigint auto_increment primary key, ## 自增主键,业务无关 host_ip varchar(50), ## 备份机IP host_port int, ## 备份机端口 backup_type varchar(50), ## 备份类型,mysqldump和xtrabackup start_time datetime, ## 备份开始时间 end_time datetime, ## 备份结束时间 backup_message varchar(5000), ## 备份消息 check_time datetime ##写入或更新记录的时间 );
一样数据容易来减小表关联,虽然最后一次成功的备份记录确定和full_backup_log表中的备份记录对应,可是由于保存数据已经所有冗余,就无需在表full_backup_info中增长字段与表full_backup_log进行关联
##================================================================##
第四版
当备份进程过分使用CPU和IO资源致使性能问题并报警后,DBA须要第一时间判断报警服务器是否处于备份过程当中,须要查看那些服务器正在进行备份:
方法1:经过full_backup_log表的start_time和end_time来获取当前正在备份的服务器,须要对end_time来建索引,若是end_time默认为NULL,则WHERE end_time is null or end_time >now, 性能很容易因OR而受影响,能够考虑给end_time设置一个默认值如2199-01-01啥的,将查询改成 where end_time >now
方法2:将full_backup_log表中is_success列扩展来标识备份状态,若是1表示成功0表示失败-1表示正在备份,查询条件为where is_success=-1,须要为is_success列建索引,可是is_success列选择性过低,而MySQL又不支持过滤索引,容易生成不高效的执行计划。
解决办法:
新建一个表,专门存放正在备份的服务器记录,这样只须要查询该表即可以获取到全部正在备份的服务器列表,备份成功后当即删除该表记录。
## full_backup_in_process用来存放正在备份的服务器信息 create table full_backup_in_process ( id bigint auto_increment primary key, ## 自增主键,业务无关 host_ip varchar(50), ## 备份机IP host_port int, ## 备份机端口 backup_type varchar(50), ## 备份类型,mysqldump和xtrabackup start_time datetime, ## 备份开始时间 check_time datetime ##写入或更新记录的时间 );
##================================================================##
总结:
部分研发同事在进行设计时,随着需求变化不停地修改表,经过在原表上新增字段来解决新需求,致使表字段过多,同一表处理不一样需求,或经过复杂的SQL来实现,逼着DBA去优化SQL或建立一堆的低效索引,且美名其曰“业务需求”。但不少需求其实能够曲线处理,每每优化业务需求和优化实现方式才能最终解决性能问题。
曾经有研发同事让帮其优化SQL,发现其业务需求是对几千万数据进行排序分页而后取TOP,几十秒都没法返回结果,建议其去除排序,被告知部分数据须要优先处理,而这部分须要优先处理的数据极少极少,最终解决办法是将优先处理的数据分拆出来让单独的程序进行处理,其余普通数据不排序查询正常处理,完美解决。
虽然开个拖拉机,能够拉货,能够耕田,也能代步,家里没电还能当个发电机,可是人生不能一个拖拉机就解决了吧!
##================================================================##
依旧是妹子镇压帖子!
推女郎艾栗栗,拿走不谢!