麦粉社区
>
帖子详情

[系统运维] 【备份瘦身】SmartBI知识库备份文件缩小实战指南

动态中心 发表于 3 小时前
发表于 3 小时前

一、问题描述


在日常使用SmartBI过程中,许多用户会遇到以下困扰:


磁盘空间频繁告警:知识库备份文件动辄几百M,随着备份次数增加,磁盘空间迅速被占满。


备份过程耗时过长:完整备份需要数小时甚至更久,经常因超时而失败。


存储成本居高不下:为满足合规要求需长期保留多个历史备份,磁盘扩容成本持续增加。


这些问题的根源,都指向同一个事实:知识库备份文件太大了


 


二、根本原因


SmartBI知识库(存储资源、报表、用户设置等元数据的数据库)中包含两类数据,它们的性质和重要性截然不同:


 




















数据类别 包含内容 是否必须备份
核心资源表 报表定义、用户信息、权限配置、数据源连接等 必须备份,系统恢复的关键
日志记录表 操作日志、任务运行历史、调度日志、 计划任务记录等 可选择性排除,仅用于审计查询

 


 


问题的关键:日志记录表会随着系统使用时间推移,持续积累海量数据,膨胀到几百MB甚至GB级别。常规的全量备份会把这些“冗余”数据一并打包,导致备份文件体积失控。


 


三、核心原理


备份瘦身的核心原理非常简单:在备份时主动排除那些体积庞大但并非系统恢复必需的日志表


为什么可以这样做?


日志表仅用于:



  • 后台查看操作记录

  • 监控任务执行历史

  • 调度日志追溯


它们不是系统恢复的必要组件。排除日志表生成的备份文件,在恢复后:



  • ✅ 所有报表完整可用

  • ✅ 所有用户和权限设置保留

  • ✅ 所有数据源连接配置正常

  • ❌ 仅操作日志、任务历史记录无法追溯(如需审计,请单独保留一份全量备份)


预期效果


通过排除日志表,备份文件体积可缩小20%-40%,备份耗时从小时级降至分钟级。


 


四、操作步骤


SmartBI提供了两种备份方式:手工备份(一次性)和自动备份(周期性)。两种方式的瘦身配置原理完全相同,您可以根据实际需求选择使用。


方式一:手动备份


适用场景:系统升级前、迁移前、重大变更前的临时备份。


操作步骤



  1. 登录SmartBI,进入 系统运维 > 知识库备份

  2. 选择仅备份非日志表


IMG_256


 


效果验证:备份完成后,对比此次备份文件与历史全量备份文件的大小,体积应有显著下降


方式二:自动备份(适用于周期性需求)


适用场景:日常定期备份,长期节省磁盘空间。


SmartBI产品自带的备份任务默认执行全表备份,无法在界面上配置拆分或排除特定表。要实现备份瘦身,就需要对自带的备份代码进行修改,创建一个自定义的瘦身备份任务。


备份源码分析


产品自带的备份任务代码如下:


importPackage(Packages.java.lang);
importPackage(Packages.java.io);
importPackage(Packages.smartbi.repository);
importPackage(Packages.smartbi.util);
function DateStr(){
var d = new Date();
var s = "";
s += d.getFullYear() + "_";
s += (d.getMonth() + 1) + "_";
s += d.getDate() + "_";
s += d.getHours() + "_";
s += d.getMinutes() + "_";
s += d.getSeconds() ;
return(s);
}
var maxCount = 30; //最多的备份数
//var context = ConfigHelper.getInstance().getContext();
var appName = CommonUtil.getInstance().getConfigKeyName(ConfigHelper.getInstance().getContext(), null);
var floderName = ServerUtil.getConfigFileDir() + "./" + appName + "_repoBackup"; //备份目录
var name = "backup_"+DateStr()+".zip";
var floder = new File(floderName);
floder.mkdirs();
var backupFile = new File(floderName+"/"+name);
var fos = new FileOutputStream(backupFile);
var br = new BackupResources();
try{
br.backupRepository(fos,true);
}catch(e){
fos.close();
backupFile.delete();
logger.info("backup fail:" + name );
throw e;
}
fos.flush();
fos.close();
var allBackup = floder.listFiles();
var allCount = allBackup.length;
if (allCount > maxCount) {
for (var i=0;i for (var j=i+1;j if (allBackup[i].lastModified() < allBackup[j].lastModified()) {
var temp = allBackup[i];
allBackup[i] = allBackup[j];
allBackup[j] = temp;
}
}
}
//删掉老的
for (var i = maxCount;i allBackup[i].delete();
}
}

代码逻辑分析


通过分析上述代码,可以梳理出备份任务的核心执行流程:



  1. 参数初始化:设置最大备份保留数(默认30个)

  2. 目录准备:获取应用名称,构建备份目录路径,创建目录

  3. 文件命名:根据当前时间生成备份文件名(格式:backup_YYYY_MM_DD_HH_mm_ss.zip)

  4. 执行备份:实例化BackupResources对象,调用backupRepository方法执行备份

  5. 异常处理:备份失败时关闭流并删除临时文件

  6. 数量控制:备份成功后,检查备份目录中的文件数量,超过maxCount时删除最旧的文件


关键代码定位


实现备份瘦身的关键在于第4步中的br.backupRepository(fos, true)方法。该方法负责将知识库内容备份到输出流中,第二个参数true表示全量备份。


通过查看BackupResources类的源码,可以发现backupRepository方法内部会遍历知识库中的所有表并逐一备份。这里就是我们需要修改的核心位置


修改思路


实现仅备份非日志表的修改策略:


 

















策略 修改位置 实现方式 说明
策略A:新增参数 备份任务脚本 调用br.back(fos,denyTables(需要排除的表)),将需要排除的表从备份列表中移除 无需修改底层代码,仅在脚本层处理

 


修改后的具体代码:


importPackage(Packages.java.lang);
importPackage(Packages.java.io);
importPackage(Packages.smartbi.repository);
importPackage(Packages.smartbi.util);
function DateStr(){
var d = new Date();
var s = "";
s += d.getFullYear() + "_";
s += (d.getMonth() + 1) + "_";
s += d.getDate() + "_";
s += d.getHours() + "_";
s += d.getMinutes() + "_";
s += d.getSeconds() ;
return(s);
}
var maxCount = 30; //最多的备份数
//var context = ConfigHelper.getInstance().getContext();
var appName = CommonUtil.getInstance().getConfigKeyName(ConfigHelper.getInstance().getContext(), null);
var floderName = ServerUtil.getConfigFileDir() + "./" + appName + "_repoBackup"; //备份目录
var name = "backup_"+DateStr()+".zip";
var floder = new File(floderName);
floder.mkdirs();
vr backupFile = new File(floderName+"/"+name);
var fos = new FileOutputStream(backupFile);
var br = new BackupResources();
var denyTables = "['t_operationlog','t_operationlog_detail','t_session','t_ssreport_writebacklog','t_offline_publishpack','t_fileresource']";//需要移除表
br.backup(fos,denyTables);
fos.flush();
fos.close();
var allBackup = floder.listFiles();
var allCount = allBackup.length;
if (allCount > maxCount) {
for (var i=0;i for (var j=i+1;j if (allBackup[i].lastModified() < allBackup[j].lastModified()) {
var temp = allBackup[i];
allBackup[i] = allBackup[j];
allBackup[j] = temp;
}
}
}
//删掉老的
for (var i = maxCount;i allBackup[i].delete();
}
}

针对具体大版本存在的日志表如下:


V11日志表包含:t_operationlog,t_operationlog_detail,t_session,t_session_info,t_schedulelog,t_ssreport_writebacklog,t_tasklog,t_access_log,t_timeconsuming,t_timeconsuming_history,


tx_extractlog,tx_extractlog_detail,tx_realextractlog,tx_augment_import_task,tx_augment_import_task_log,t_daq_import_log


 


V10.5.15日志表包含:t_operationlog,t_operationlog_detail,t_session,t_schedulelog,t_ssreport_writebacklog,t_tasklog,tx_extractlog,tx_extractlog_detail,tx_realextractlog,t_daq_import_log 


 


V10.5.8日志表包含:tx_extractlog,tx_extractlog_detail,tx_realextractlog,t_daq_import_log,t_operationlog,t_operationlog_detail,t_session,t_schedulelog,t_ssreport_writebacklog,t_tasklog


 


V95日志表包含:t_operationlog、t_operationlog_detail、t_session、t_ssreport_writebacklog、t_tasklog、t_schedulelog、t_daq_import_log、tx_extractlog、tx_realextractlog


 


V856日志表包含:t_operationlog、t_operationlog_detail、t_session、t_ssreport_writebacklog、t_tasklog、t_schedulelog、t_daq_import_log


 


V72日志表包含:t_operationlog、t_operationlog_detail、t_session、t_ssreport_writebacklog、t_tasklog、t_schedulelog、t_daq_import_log

高级模式
B Color Image Link Quote Code Smilies
您需要登录后才可以回帖 登录 | 立即注册

0回帖数 0关注人数 28浏览人数
最后回复于:3 小时前

社区

指南

AI

搜索

快速回复 返回顶部 返回列表