schemas模式导出仅含对象结构,不包含用户权限等元数据,因其不访问dba_*权限视图;需用full=y+content=metadata_only+include指定项导出用户及权限。
单纯用 expdp 导出用户数据(比如 schemas=app_user),默认不会导出该用户的密码、角色权限、系统权限、对象权限、默认表空间、临时表空间等元数据——这些信息藏在数据字典里,不在用户模式对象中。
为什么 SCHEMAS 模式导出不包含用户权限
Oracle Data Pump 的 SCHEMAS 模式本质是「导出指定 schema 下的数据库对象(表、视图、过程等)及其依赖结构」,它不触碰 DBA_USERS、DBA_ROLE_PRIVS、DBA_SYS_PRIVS、DBA_TAB_PRIVS 这类全局权限视图。即使你加了 CONTENT=ALL,它也只影响对象内容(如表数据、统计信息),不影响用户账户定义本身。
常见现象:导入后用户能连上,但报 ORA-01031: insufficient privileges;或者用户存在但没被授予 CREATE SESSION;或者 SELECT ANY TABLE 权限丢了。
所以,要备份「用户及其权限」,必须显式导出元数据,且不能依赖 SCHEMAS 参数。
用 METADATA_ONLY + FULL=Y 导出用户账户和权限
最直接的方式是走全库元数据导出,但仅提取用户相关部分。关键点在于:FULL=Y 是前提,否则 INCLUDE 过滤无效;CONTENT=METADATA_ONLY 确保不导数据,只导定义;INCLUDE 精确限定范围。
执行命令前确保你有 EXP_FULL_DATABASE 角色(或 DATAPUMP_EXP_FULL_DATABASE 在 12c+):
expdp '/ as sysdba' \ FULL=Y \ CONTENT=METADATA_ONLY \ INCLUDE=USER,ROLE,ROLE_GRANT,DEFAULT_ROLE,SYSTEM_GRANT,OBJECT_GRANT,TABLESPACE_QUOTA,PROFILE \ DIRECTORY=DATA_PUMP_DIR \ DUMPFILE=user_meta_20260413.dmp \ LOGFILE=user_meta_20260413.log
说明:
-
INCLUDE=USER:导出CREATE USER语句(含密码哈希、default/temprary tablespace、profile、account status) -
ROLE和ROLE_GRANT:导出角色定义及用户被授角色的动作 -
SYSTEM_GRANT:导出GRANT CREATE SESSION TO app_user这类系统权限 -
OBJECT_GRANT:导出GRANT SELECT ON hr.employees TO app_user这类对象权限 -
TABLESPACE_QUOTA:导出配额信息,如ALTER USER app_user QUOTA UNLIMITED ON users - 不加
EXCLUDE=SCHEMA或类似过滤,否则可能误删用户对象定义
单独导出单个用户的权限(不导其他用户)
如果只要备份 app_user 的权限,又不想导全库元数据,可用 SQLFILE + INCLUDE 组合生成可读 SQL 脚本,再人工筛选或脚本处理:
expdp '/ as sysdba' \ SCHEMAS=app_user \ CONTENT=METADATA_ONLY \ INCLUDE=SYSTEM_GRANT,OBJECT_GRANT,ROLE_GRANT,DEFAULT_ROLE,TABLESPACE_QUOTA \ SQLFILE=app_user_privs.sql \ DIRECTORY=DATA_PUMP_DIR \ LOGFILE=app_user_privs.log
注意:SCHEMAS=app_user 在这里只是用来限定权限归属上下文,不是导出其表——CONTENT=METADATA_ONLY 已跳过所有对象导出。生成的 app_user_privs.sql 里会包含所有授给该用户的权限语句,但不含 CREATE USER(因为 USER 不在 INCLUDE 列表里)。
若需完整重建用户,得额外补上:
SELECT 'CREATE USER ' || username || ' IDENTIFIED BY VALUES ''' || password || ''' DEFAULT TABLESPACE ' || default_tablespace || ' TEMPORARY TABLESPACE ' || temporary_tablespace || ' PROFILE ' || profile || ' ACCOUNT ' || account_status || ';' FROM dba_users WHERE username = 'APP_USER';
⚠️ 密码是哈希值(PASSWORD 列),无法还原明文,但可直接用于 CREATE USER ... IDENTIFIED BY VALUES 重建相同密码状态。
导入时权限不会自动生效的两个坑
即使 dump 文件里包含了完整权限定义,导入时仍可能失败或静默跳过:
-
impdp默认以当前连接用户身份执行 DDL,如果该用户没有ADMIN OPTION(比如被授了SELECT ANY TABLE但没带WITH ADMIN OPTION),则无法把该权限再转授出去——导入日志里会出现ORA-39142: incompatible version number或直接忽略该GRANT行 - 目标库已存在同名用户,且未加
REMAP_SCHEMA或TABLE_EXISTS_ACTION=REPLACE,CREATE USER会报错并中断后续权限导入;建议先用sqlplus手动DROP USER app_user CASCADE,或加EXCLUDE=USER单独处理用户创建 - Profile 不存在时,
CREATE USER会失败;导入前应确认目标库已有对应PROFILE,或在impdp中加EXCLUDE=PROFILE并手动创建
真正可靠的权限恢复,往往需要分两步:先用 SQLFILE 生成脚本,人工检查、去重、补缺,再用 sqlplus 执行;而不是全依赖 impdp 自动还原。











