
知识是人生的灯塔,只有不断学习,才能照亮前行的道路
📢 大家好,我是 WeiyiGeek,一名深耕安全运维开发(SecOpsDev)领域的技术从业者,致力于探索DevOps与安全的融合(DevSecOps),自动化运维工具开发与实践,企业网络安全防护,欢迎各位道友一起学习交流、一起进步 🚀,若此文对你有帮助,一定记得倒点个关注⭐与小红星❤️,收藏学习不迷路 😋 。
0x01 使用传统数据导出/导入 (exp/imp) 工具恢复性测试
描述:本文作者将详细介绍、并实践,如何在 Oracle 数据库中使用传统的exp和imp工具进行全库备份和恢复性测试;这对于数据库管理员来说是一个基础且重要的技能,尤其是在需要快速恢复数据或迁移环境时非常有用。
特别注意,使用传统工具进行备份、恢复性测试时,需要注意以下几点:
-
字符集:确保源库和目标库的字符集一致,否则可能导致乱码。
-
性能:在处理大量数据时可能较慢,会占用大量系统资源,尽量在业务低峰期进行。
-
版本:通常低版本exp导出文件可被高版本的imp工具导入,反之则不行,但尽量使用相同或相近版本的客户端工具。
温馨提示:传统工具适用于较小的数据库,并且在所有Oracle版本中具有很好的兼容性,但在新版本的Oracle中(尤其是12c及以上),强烈建议使用更现代、更高效的数据泵(Data Pump)工具,即 expdp 和 impdp 下一小节将详细介绍。
温馨提示:下述实践作者将以 Oracle 12c 为例进行演示,但请注意,这些步骤在大多数版本的Oracle数据库中都是通用的。
温馨提示:若文章代码块中存在乱码,请通过文末的阅读原文链接,在知识星球中阅读,或者直接访问原文链接:https://articles.zsxq.com/id_kn8segbgb18z.html
exp 命令参数
go
# 查看帮助
exp HELP=Y
# 交互式
exp USERID=账号/<密码>@<实例名>
# 命令行式
exp USERID="账号/<密码>@<实例名>" FULL=Y FILE=<备份文件路径> LOG=<日志文件路径> STATISTICS=NONE
# 特别注意:USERID 必须是命令行中的第一个参数。
关键字 说明 (默认值) 关键字 说明 (默认值)
--------------------------------------------------------------------------
USERID 用户名/口令 FULL 导出整个文件 (N)
BUFFER 数据缓冲区大小 OWNER 所有者用户名列表
FILE 输出文件 (EXPDAT.DMP) TABLES 表名列表
COMPRESS 导入到一个区 (Y) RECORDLENGTH IO 记录的长度
GRANTS 导出权限 (Y) INCTYPE 增量导出类型
INDEXES 导出索引 (Y) RECORD 跟踪增量导出 (Y)
DIRECT 直接路径 (N) TRIGGERS 导出触发器 (Y)
LOG 屏幕输出的日志文件 STATISTICS 分析对象 (ESTIMATE)
ROWS 导出数据行 (Y) PARFILE 参数文件名
CONSISTENT 交叉表的一致性 (N) CONSTRAINTS 导出的约束条件 (Y)
OBJECT_CONSISTENT 只在对象导出期间设置为只读的事务处理 (N)
FEEDBACK 每 x 行显示进度 (0)
FILESIZE 每个转储文件的最大大小
FLASHBACK_SCN 用于将会话快照设置回以前状态的 SCN
FLASHBACK_TIME 用于获取最接近指定时间的 SCN 的时间
QUERY 用于导出表的子集的 select 子句
RESUMABLE 遇到与空格相关的错误时挂起 (N)
RESUMABLE_NAME 用于标识可恢复语句的文本字符串
RESUMABLE_TIMEOUT RESUMABLE 的等待时间
TTS_FULL_CHECK 对 TTS 执行完整或部分相关性检查
TABLESPACES 要导出的表空间列表
TRANSPORT_TABLESPACE 导出可传输的表空间元数据 (N)
TEMPLATE 调用 iAS 模式导出的模板名
imp 命令参数
go
# 查看帮助
imp HELP=Y
# 交互式
imp USERID=账号/<密码>@<实例名>
# 命令行式
imp USERID="账号/<密码>@<实例名>" FULL=Y FILE=/backup/full.dmp LOG=/backup/imp_full.log IGNORE=Y
# 同样 USERID 必须是命令行中的第一个参数。
关键字 说明 (默认值) 关键字 说明 (默认值)
--------------------------------------------------------------------------
USERID 用户名/口令 FULL 导入整个文件 (N)
BUFFER 数据缓冲区大小 FROMUSER 所有者用户名列表
FILE 输入文件 (EXPDAT.DMP) TOUSER 用户名列表
SHOW 只列出文件内容 (N) TABLES 表名列表
IGNORE 忽略创建错误 (N) RECORDLENGTH IO 记录的长度
GRANTS 导入权限 (Y) INCTYPE 增量导入类型
INDEXES 导入索引 (Y) COMMIT 提交数组插入 (N)
ROWS 导入数据行 (Y) PARFILE 参数文件名
LOG 屏幕输出的日志文件 CONSTRAINTS 导入限制 (Y)
DESTROY 覆盖表空间数据文件 (N)
INDEXFILE 将表/索引信息写入指定的文件
SKIP_UNUSABLE_INDEXES 跳过不可用索引的维护 (N)
FEEDBACK 每 x 行显示进度 (0)
TOID_NOVALIDATE 跳过指定类型 ID 的验证
FILESIZE 每个转储文件的最大大小
STATISTICS 始终导入预计算的统计信息
RESUMABLE 在遇到有关空间的错误时挂起 (N)
RESUMABLE_NAME 用来标识可恢复语句的文本字符串
RESUMABLE_TIMEOUT RESUMABLE 的等待时间
COMPILE 编译过程, 程序包和函数 (Y)
STREAMS_CONFIGURATION 导入流的一般元数据 (Y)
STREAMS_INSTANTIATION 导入流实例化元数据 (N)
DATA_ONLY 仅导入数据 (N)
下列关键字仅用于可传输的表空间
TRANSPORT_TABLESPACE 导入可传输的表空间元数据 (N)
TABLESPACES 将要传输到数据库的表空间
DATAFILES 将要传输到数据库的数据文件
TTS_OWNERS 拥有可传输表空间集中数据的用户
1.全库备份&恢复实践
温馨提示:若要导出 Oracle 实例中全部数据则需要具有EXP_FULL_DATABASE角色的用户(如sys或system)来执行,但是通常情况下,我们仅会针对特定用户或表进行备份。
实践流程
步骤 01.查看当前用户是否具有EXP_FULL_DATABASE角色:
go
SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE = 'EXP_FULL_DATABASE';
GRANTEE
-----------------
GRANTED_ROLE ADM DEL DEF COM INH
----------------- --- --- --- --- ---
DBA
EXP_FULL_DATABASE NO NO YES YES YES
DATAPUMP_EXP_FULL_DATABASE
EXP_FULL_DATABASE NO NO YES YES YES
SYS
EXP_FULL_DATABASE YES NO YES YES YES
DATAPUMP_IMP_FULL_DATABASE
EXP_FULL_DATABASE NO NO YES YES YES
步骤 02.创建测试表以及模拟数据。
go
-- # 创建表空间
CREATETABLESPACE itgeekdata DATAFILE'C:\app\oracle\oradata\bkhistdb\itgeekdata01.dbf'SIZE100M autoextendoff;
ALTERTABLESPACE itgeekdata ADDDATAFILE'C:\app\oracle\oradata\bkhistdb\itgeekdata02.dbf'SIZE100M autoextendoff;
ALTERTABLESPACE itgeekdata ADDDATAFILE'C:\app\oracle\oradata\bkhistdb\itgeekdata03.dbf'SIZE100M autoextendoff;
-- # 创建临时表空间
CREATETEMPORARYTABLESPACE itgeektemp TEMPFILE 'C:\app\oracle\oradata\bkhistdb\itgeektemp01.dbf'size100m autoextendoff;
-- # 创建用户 itgeek 密码为 Password123
CREATEUSER itgeek IDENTIFIEDBY Password123 DEFAULTTABLESPACE itgeekdata TEMPORARYTABLESPACE itgeektemp;
-- # 授予权限
grantconnect,resourceto itgeek;
ALTERUSER itgeek QUOTAUNLIMITEDON ITGEEKDATA;
-- # 新建命令行终端,使用 itgeek 用户登录。
sqlplus 'itgeek/Password123@127.0.0.1:1521/bkhistdb'
-- 在itgeek用户下执行以下命令
-- 创建测试表
CREATETABLE emp (
idINT primary key,
nameVARCHAR(10) NOTNULL,
gender CHAR(1) NOTNULL,
age INTNOTNULL
);
-- 添加字段注释
COMMENTONCOLUMN emp.id IS'员工ID';
COMMENTONCOLUMN emp.name IS'员工姓名';
COMMENTONCOLUMN emp.gender IS'员工性别';
COMMENTONCOLUMN emp.age IS'员工年龄';
-- 通过数据字典查看注释
SELECT * FROM user_col_comments WHERE table_name = 'emp';
-- 清空表(如果已有数据)
-- TRUNCATE TABLE emp;
-- 批量插入测试数据
INSERTALL
INTO emp VALUES (1, '张三', 'M', 28)
INTO emp VALUES (2, '李四', 'F', 32)
INTO emp VALUES (3, '王五', 'M', 25)
INTO emp VALUES (4, '赵六', 'F', 29)
INTO emp VALUES (5, '钱七', 'M', 35)
INTO emp VALUES (6, '孙八', 'F', 27)
INTO emp VALUES (7, '周九', 'M', 31)
INTO emp VALUES (8, '吴十', 'F', 26)
SELECT1FROM DUAL;
-- 提交事务
COMMIT;
weiyigeek.top-测试表与数据模拟图
步骤 03.使用 sys 用户进行 Oracle bkhistdb 实例全库备份,若显示 成功终止导出, 没有出现警告 则表示备份成功。
go
# Windows(cmd)
mkdir c:\backup
exp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" FULL=Y FILE=c:/backup/full_%date:~0,4%%date:~5,2%%date:~8,2%.dmp LOG=c:/backup/exp_full_%date:~0,4%%date:~5,2%%date:~8,2%.log STATISTICS=NONE COMPRESS=Y
# Linux
mkdir /backup
exp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" FULL=Y FILE=/backup/full_$(date +%Y%m%d).dmp LOG=/backup/exp_full_$(date +%Y%m%d).log STATISTICS=NONE COMPRESS=Y
# 参数解释
USERID:指定具有足够权限的用户名和密码
FULL=Y:表示进行全库导出
FILE:指定导出的备份文件路径和名称(例如:/backup/full_backup.dmp)
LOG:指定导出过程的日志文件路径,便于排查问题
STATISTICS=NONE:在导出时不生成统计信息,可以加快导出速度
COMPRESS=Y:将碎片整理为一个区域,这可能会减少DMP文件的大小
CONSISTENT=Y:确保导出的数据在某个时间点是一致的,对于大型数据库,这可能会产生大量 undo 需谨慎使用
# 查看备份文件
C:\Users\Administrator>dir c:\backup\*.*
驱动器 C 中的卷是 系统保留
卷的序列号是 B087-BF42
2025/10/28 12:02 2,125 exp_full_20251028.log
2025/10/28 12:02 1,439,744 full_20251028.dmp
weiyigeek.top-Oracle 全库备份图
步骤 04.模拟数据丢失,大致以三种情况为例,再进行恢复验证。
go
-- 方式1,将itgeek用户下的表数据清空,模拟数据丢失 (单表)
SQL> truncate table emp;
SQL> select * from emp;
未选定行
-- 方式2,删除itgeek用户下的一行数据,模拟单条记录丢失(单行)
SQL> delete from emp where id=7;
-- 方式3:删除用户 itgeek 模式数据,模拟用户丢失(单用户)
drop user itgeek cascade;
温馨提示:使用 imp 恢复数据时由于其没有提供覆盖原有数据库表,这里我们先将创建的用户 itgeek 进行删除后模拟。
步骤 05.当需要恢复或迁移整个数据库时到新环境时,则可使用 imp 命令,通过前面的 full_20251028.dmp 备份文件进行 Oracle bkhistdb 实例全库恢复。
go
# 导入备份实例 (Windows)
imp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" FULL=Y FILE=c:\\backup\\full_20251028.dmp LOG=c:\\backup\\imp_full_20251028.log IGNORE=Y
# linux
imp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" FULL=Y FILE=/backup/full_20251028.dmp LOG=/backup/imp_full_20251028.log IGNORE=Y
# 参数解释:
USERID:目标数据库的具有足够权限的用户。
FULL=Y:表示进行全库导入。
FILE:指定之前导出的DMP文件路径。
LOG:指定导入过程的日志文件。
IGNORE=Y:忽略创建对象时可能出现的错误(例如对象已存在),这在恢复时非常有用。
weiyigeek.top-导入备份实例图
步骤 06.使用 sys 或者 itgeek 用户登录,查看恢复后的数据,由下图可以看到不但删除的 itgeek 用户恢复了,里面的数据也恢复了。
go
> sqlplus 'itgeek/Password123@127.0.0.1:1521/bkhistdb'
SQL> select * from emp;
weiyigeek.top-查看数据恢复图
特别注意:若恢复已有数据库表,更新原有数据时,通常建议先 truncate table 原有表再进行导入,否则将会在恢复时因为约束无法导入通过 update 语句修改的数据行,但是 delete 语句删除的数据行则可以正常恢复,但是会出现数据行向后追加的情况。
go
SQL> select * from emp;
ID NAME G AGE
---------- ---------- - ----------
1 张三 M 28
2 李四 F 32
3 王五 M 25
4 赵六 F 29
5 钱七 M 35
6 孙八 F 27
8 吴十 F 26
7 周九 M 31 -- 恢复的数据行向后追加,这当然不是我们想要的效果。
已选择 8 行。
2.指定用户模式备份&恢复实践 (常用)
描述:通常情况下我们只需要备份某个用户模式下的数据,而不是整个数据库,同样我们还是以 itgeek 用户为例进行演示。
操作流程
步骤 01.使用 sys 或者 itgeek 用户登录,查看现有数据。
go
-- sys 用户登录时
select * from itgeek.emp;
-- itgeek 用户登录时
select * from emp;
步骤 02.使用 sys、itgeek 用户登录,对 itgeek 模式下的 emp 表进行备份。
go
-- 使用 sys 用户
exp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" OWNER=itgeek FILE=/backup/itgeek_sys_backup.dmp LOG=/backup/exp_itgeek_sys_backup.log STATISTICS=NONE
-- 使用 itgeek 用户
exp USERID=\"itgeek/Password123@127.0.0.1:1521/bkhistdb\" OWNER=itgeek FILE=/backup/itgeek_backup.dmp LOG=/backup/exp_itgeek_backup.log STATISTICS=NONECOMPRESS=Y
-- 参数解释:
OWNER=itgeek:指定要导出的用户(模式)
FILE:导出的备份文件路径
LOG:导出过程日志文件
STATISTICS=NONE:不生成统计信息,加快导出速度
COMPRESS=Y:压缩碎片,可能减少文件大小
BUFFER=102400:设置数据缓冲区大小(字节)
GRANTS=Y:导出权限信息
INDEXES=Y:导出索引
CONSTRAINTS=Y:导出约束
步骤 03.模拟数据丢失,便于后续进行恢复验证。
go
# 方式1.将itgeek用户下的表数据清空,模拟数据丢失 (单表)
SQL> TRUNCATE TABLE emp;
表被截断。
# 方式2.删除itgeek用户下的一行数据,模拟单条记录丢失 (单行)
SQL> DELETE FROM emp WHERE id=7;
已删除 1 行。
步骤 04.使用 sys 或者 itgeek 用户登录,对 itgeek 模式下的 emp 表进行恢复。
go
-- 使用 sys 用户
imp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" FILE=c:/backup/itgeek_sys_backup.dmp LOG=c:/backup/imp_itgeek_sys_backup.log FROMUSER=itgeek TOUSER=itgeek IGNORE=Y COMMIT=Y
-- 使用 itgeek 用户
imp USERID=\"itgeek/Password123@127.0.0.1:1521/bkhistdb\"FILE=c:/backup/itgeek_backup.dmp LOG=c:/backup/imp_itgeek_backup.log FROMUSER=itgeek TOUSER=itgeek IGNORE=Y COMMIT=Y
-- 恢复到其他用户(如itgeek_bak)
imp USERID=\"itgeek/Password123@127.0.0.1:1521/bkhistdb\"FILE=c:/backup/itgeek_backup.dmp LOG=c:/backup/imp_itgeek_backup.log FROMUSER=itgeek TOUSER=itgeek_bak IGNORE=Y COMMIT=Y ROWS=N
-- 仅导入表结构(不导入数据)
imp USERID=\"itgeek/Password123@127.0.0.1:1521/bkhistdb\"FILE=c:/backup/itgeek_backup.dmp LOG=c:/backup/imp_itgeek_backup.log FROMUSER=itgeek TOUSER=itgeek IGNORE=Y COMMIT=Y ROWS=N
-- 仅导入数据(表结构已存在)
imp USERID=\"itgeek/Password123@127.0.0.1:1521/bkhistdb\"FILE=c:/backup/itgeek_backup.dmp LOG=c:/backup/imp_itgeek_backup.log FROMUSER=itgeek TOUSER=itgeek IGNORE=Y COMMIT=Y ROWS=Y CONSTRAINTS=N
-- 重要参数说明:
FROMUSER=itgeek:指定源用户(导出文件中的用户)
TOUSER=itgeek:指定目标用户
IGNORE=Y:忽略创建错误(如表已存在)
COMMIT=Y:每个数据数组提交,避免回滚段过大
ROWS=Y/N:是否导入数据行
CONSTRAINTS=N: 不导入约束信息
步骤 05.使用 sys 或者 itgeek 用户登录,查看恢复后的数据,若下图所属。
go
-- 使用方式1模拟删除数据,并恢复到原有用户 itgeek 结果展示
SQL> select * from emp;
-- 使用方式2模拟删除数据,仅导入数据(表结构已存在)并忽略约束信息结果
SQL> select * from emp;
...
8 吴十 F 26
7 周九 M 31 -- 关键点
...
-- 仅导入表结构(不导入数据)结果展示
SQL> desc emp;
名称 是否为空? 类型
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(38)
NAME NOT NULL VARCHAR2(10)
GENDER NOT NULL CHAR(1)
AGE NOT NULL NUMBER(38)
weiyigeek.top-指定用户数据恢复图
3.其它示例
例1.导出特定表数据,并指定查询条件,并恢复到指定表以及表空间。
go
# 导出数据
exp itgeek/Password123@127.0.0.1:1521/bkhistdb FILE=c:/backup/itgeek_emp_query.dmp LOG=c:/backup/itgeek_emp_query.log TABLES=emp QUERY=\"WHERE id>4\"
# 即将导出指定的表通过常规路径...
# . . 正在导出表 EMP导出了 4 行
# EXP-00091: 正在导出有问题的统计信息。
# 导出成功终止, 但出现警告。
# 清空表用以测试
TRUNCATE TABLE emp;
# 导入数据(以 sys 用户为例)
imp USERID=\"sys/WeiyiGeektop2025@127.0.0.1:1521/bkhistdb as sysdba\" FILE=c:/backup/itgeek_emp_query.dmp LOG=c:/backup/imp_itgeek_emp_query.log fromuser=itgeek touser=itgeek tables=emp tablespaces=itgeekdata ignore=y
# 查看恢复的数据
SELECT * FROM emp;
weiyigeek.top-条件导出以及数据恢复图
4.常见问题
问题1:权限不足
错误信息:EXP-00023: 无法检查用户存在性解决方案 使用更高权限用户执行导出
go
exp USERID=system/<system密码>@orcl OWNER=itgeek FILE=...
问题2:表空间不存在
错误信息: IMP-00017: 表空间不存在解决方案: 在导入前创建所需的表空间,或使用REMAP_TABLESPACE参数(在imp中有限制)
问题3:对象已存在
解决方案:使用IGNORE=Y参数,或在导入前删除目标用户下的所有对象
问题4:字符集不匹配
解决方案:确保源数据库和目标数据库字符集一致
go
SQL> SELECT * FROM nls_database_parameters WHERE parameter LIKE '%CHARACTERSET%';
PARAMETER
-------
VALUE
------------
NLS_NCHAR_CHARACTERSET
AL16UTF16
NLS_CHARACTERSET
ZHS16GBK
5.备份脚本
作者以 Linux 环境为例,编写了一个简单的备份脚本。该脚本将导出指定用户的数据并压缩备份文件,同时清理30天前的旧备份文件。您可以根据需要修改用户名、密码和服务名等参数。
go
#!/bin/bash
# itgeek_user_backup.sh
# 配置变量
USERNAME="itgeek"
PASSWORD="your_password"
SERVICE_NAME="orcl"
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${USERNAME}_backup_${DATE}.dmp"
LOG_FILE="${BACKUP_DIR}/exp_${USERNAME}_${DATE}.log"
# 执行导出
echo"开始导出用户 ${USERNAME}..."
exp USERID=${USERNAME}/${PASSWORD}@${SERVICE_NAME} \
OWNER=${USERNAME} \
FILE=${BACKUP_FILE} \
LOG=${LOG_FILE} \
STATISTICS=NONE \
GRANTS=Y \
INDEXES=Y \
CONSTRAINTS=Y
# 检查导出结果
if [ $? -eq 0 ]; then
echo"导出成功: ${BACKUP_FILE}"
# 压缩备份文件以节省空间
gzip ${BACKUP_FILE}
echo"备份文件已压缩"
else
echo"导出失败,请检查日志: ${LOG_FILE}"
exit 1
fi
# 清理30天前的备份文件
find ${BACKUP_DIR} -name "${USERNAME}_backup_*.dmp.gz" -mtime +30 -delete
echo"已完成旧备份清理"
如果您需要更高级的功能(如增量导出、并行处理等),强烈建议考虑使用数据泵(expdp/impdp),它在性能和功能上都优于传统工具。

END
加入:作者【全栈工程师修炼指南】知识星球
『 全栈工程师修炼指南』星球,主要涉及全栈工程师(Full Stack Development)实践文章,包括但不限于企业SecDevOps和网络安全等保合规、安全渗透测试、编程开发、云原生(Cloud Native)、物联网工业控制(IOT)、人工智能Ai,从业书籍笔记,人生职场认识等方面资料或文章。
Q: 加入作者【全栈工程师修炼指南】星球后有啥好处?
✅ 将获得作者最新工作学习实践文章以及网盘资源。
✅ 将获得作者珍藏多年的全栈学习笔记(需连续两年及以上老星球友,也可单次购买)
✅ 将获得作者专门答疑学习交流群,解决在工作学习中的问题。
✅ 将获得作者远程支持(在作者能力范围内且合规)。

获取:作者工作学习全栈笔记
作者整理了10年的工作学习笔记(涉及网络、安全、运维、开发),需要学习实践笔记的看友,可添加作者微信或者回复【工作学习实践笔记】,当前价格¥299,除了获得从业笔记的同时还可进行问题答疑以及每月远程技术支持,希望大家多多支持,收获定大于付出!

知识推荐 往期文章
若文章对你有帮助,请将它转发给更多的看友,若有疑问的小伙伴,可在评论区留言你想法哟 💬!
