数据库备份,大家都知道很重要,但手动备份有几个痛点:
人力成本高:DBA 不可能每天半夜爬起来执行备份命令。
容易遗漏:忙起来容易忘记,或者备份任务被其他事务打断。
磁盘容易满:只备份不清理,磁盘迟早被撑爆。
所以,我们需要一套自动、准时、无人值守的备份与清理策略。
本文的目标是模拟一套企业级备份策略:
备份类型 执行时间 说明
全量备份 每周六 23:00 完整备份整个数据库
增量备份 每天 23:00(除周六外) 只备份变化的数据,节省时间和空间
自动清理 每次备份后 删除 30 天前的旧备份,防止磁盘占满
联机备份依赖归档日志,但新初始化的数据库虽然开启了归档模式(ARCH_MODE=Y),可能还未配置具体的归档目录。需要先进行检查和配置。
步骤一:查看归档配置
SELECT * FROM V$DM_ARCH_INI;
初始化作业系统:SP_INIT_JOB_SYS(1) 表示创建作业系统相关的系统表和视图,执行一次即可。如果后续不需要作业系统,可以用 SP_INIT_JOB_SYS(0) 清理。
SP_INIT_JOB_SYS(1);
-- 创建全量备份作业
CALL SP_CREATE_JOB('JOB_FULL_BAK_WEEKLY', 1, 0, '', 0, 0, '', 0, '每周六23点全量备份');
CALL SP_JOB_CONFIG_START('JOB_FULL_BAK_WEEKLY');
CALL SP_ADD_JOB_STEP('JOB_FULL_BAK_WEEKLY', 'STEP_FULL_BAK', 6, '01000000/dmdata/backup/full', 1, 2, 0, 0, NULL, 0);
CALL SP_ADD_JOB_SCHEDULE('JOB_FULL_BAK_WEEKLY', 'SCH_FULL_BAK', 1, 2, 1, 64, 0, '23:00:00', NULL, SYSDATE, NULL, '');
CALL SP_JOB_CONFIG_COMMIT('JOB_FULL_BAK_WEEKLY');
CALL SP_CREATE_JOB('JOB_INCR_BAK_DAILY', 1, 0, '', 0, 0, '', 0, '每天23点增量备份(除周六)');
CALL SP_JOB_CONFIG_START('JOB_INCR_BAK_DAILY');
CALL SP_ADD_JOB_STEP('JOB_INCR_BAK_DAILY', 'STEP_INCR_BAK', 6, '11000000/dmdata/backup/incr', 1, 2, 0, 0, NULL, 0);
CALL SP_ADD_JOB_SCHEDULE('JOB_INCR_BAK_DAILY', 'SCH_INCR_BAK', 1, 2, 1, 63, 0, '23:00:00', NULL, SYSDATE, NULL, '');
CALL SP_JOB_CONFIG_COMMIT('JOB_INCR_BAK_DAILY');
验证作业:在完成全量备份作业(JOB_FULL_BAK_WEEKLY)和增量备份作业(JOB_INCR_BAK_DAILY)的创建后,通过查询系统表确认作业及调度信息。
SELECT ID, NAME, ENABLE, CREATETIME FROM SYSJOB.SYSJOBS WHERE NAME = 'JOB_FULL_BAK_WEEKLY';
SELECT ID, NAME, ENABLE, CREATETIME FROM SYSJOB.SYSJOBS WHERE NAME = 'JOB_INCR_BAK_DAILY';
SELECT JOBID, NAME, STARTTIME, FREQ_INTERVAL, FREQ_SUB_INTERVAL FROM SYSJOB.SYSJOBSCHEDULES WHERE JOBID IN (1786069082, 1786069083);
其中 ENABLE=1 表示作业已启用,CREATETIME 记录了作业的创建时间。
结果确认:
全量备份作业(SCH_FULL_BAK):每周六(FREQ_SUB_INTERVAL=64)23:00执行
增量备份作业(SCH_INCR_BAK):每天(除周六外,FREQ_SUB_INTERVAL=63)23:00执行
通过以上查询,确认两个作业均已正确配置并启用,等待调度时间自动执行即可。
由于清理操作涉及多条 SQL,先封装成存储过程再调用:
CREATE OR REPLACE PROCEDURE PROC_CLEAN_BAK AS
BEGIN
SF_BAKSET_BACKUP_DIR_ADD('DISK', '/dmdata/backup/full');
SF_BAKSET_BACKUP_DIR_ADD('DISK', '/dmdata/backup/incr');
CALL SP_DB_BAKSET_REMOVE_BATCH('DISK', SYSDATE - 30);
END;
/
创建清理作业:
CALL SP_CREATE_JOB('JOB_CLEAN_BAK', 1, 0, '', 0, 0, '', 0, '每周六全备完成后删除30天前备份');
CALL SP_JOB_CONFIG_START('JOB_CLEAN_BAK');
CALL SP_ADD_JOB_STEP('JOB_CLEAN_BAK', 'STEP_CLEAN_BAK', 0, 'CALL PROC_CLEAN_BAK();', 1, 2, 0, 0, NULL, 0);
CALL SP_ADD_JOB_SCHEDULE('JOB_CLEAN_BAK', 'SCH_CLEAN_BAK', 1, 2, 1, 64, 0, '23:30:00', NULL, SYSDATE, NULL, '');
CALL SP_JOB_CONFIG_COMMIT('JOB_CLEAN_BAK');
验证作业:
-- 查看清理作业是否创建成功
SELECT ID, NAME, ENABLE, CREATETIME FROM SYSJOB.SYSJOBS WHERE NAME = 'JOB_CLEAN_BAK';
-- 查看清理作业的调度
SELECT JOBID, NAME, STARTTIME, FREQ_INTERVAL, FREQ_SUB_INTERVAL
FROM SYSJOB.SYSJOBSCHEDULES
WHERE NAME = 'SCH_CLEAN_BAK';
结果确认:
清理作业(SCH_CLEAN_BAK)的执行时间为 23:30
频率间隔(FREQ_INTERVAL=1)表示每1周执行一次
子频率(FREQ_SUB_INTERVAL=64)对应周六
即清理作业会在每周六的 23:30 自动执行,这个时间点在全量备份作业(23:00)之后,确保了先完成备份再进行清理。
验证全量备份:
BACKUP DATABASE FULL BACKUPSET '/dmdata/backup/full/online_verify_bak';
这条命令执行失败了,返回错误【-8003】:
分析原因:数据库找不到可以存放归档日志的地方,所以拒绝执行联机备份。
解决:
1. 查询数据库当前的归档配置:
SELECT * FROM V$DM_ARCH_INI;
原因:数据库确实没有配置任何归档日志目录。
2. 创建存放归档日志的物理目录
mkdir -p /dmdata/arch
3. 将目录配置给数据库:修改归档配置必须在数据库的 MOUNT 状态下进行,不能在 OPEN 状态下操作
-- 1. 切换到 MOUNT 状态
ALTER DATABASE MOUNT;
-- 2. 添加本地归档目录配置
ALTER DATABASE ADD ARCHIVELOG 'DEST=/dmdata/arch, TYPE=local, FILE_SIZE=1024, SPACE_LIMIT=2048';
-- 3. 切回 OPEN 状态(恢复正常运行)
ALTER DATABASE OPEN;
SELECT * FROM V$DM_ARCH_INI;
之前联机备份报错 [-8003],就是因为 V$DM_ARCH_INI 里是空的(没有配置任何归档目录)。现在通过命令在 MOUNT 状态下添加了归档配置,查询结果有数据了,说明归档目录已经配好了,所以联机备份能成功。
重新执行备份命令验证成功:
BACKUP DATABASE FULL BACKUPSET '/dmdata/backup/full/online_verify_bak';
验证增量备份成功:
验证删除策略成功:
验证结论:全量备份、增量备份、清理策略均已手动触发成功,核心功能验证通过。
| 功能 | 作业名称 | 调度时间 | 手动验证 |
|---|---|---|---|
| 全量备份 | JOB_FULL_BAK_WEEKLY |
每周六 23:00 | ✅ 已通过 |
| 增量备份 | JOB_INCR_BAK_DAILY |
每天 23:00(除周六) | ✅ 已通过 |
| 删除策略 | JOB_CLEAN_BAK |
每周六 23:30 | ✅ 已通过 |
文章
阅读量
获赞
