做了十几年Oracle运维,最常被问到的还是"DBA平时都在敲什么命令"。这问题问得其实挺实在,因为很多书上讲的都是原理和概念,真到了故障现场、割接窗口或者等保测评组来了,手上有没有一套顺手、够用、不出错的命令才是关键。这篇东西就是我日常处理Oracle数据库时反复在用的核心命令集合,覆盖连接排查、存储管理、权限审计、性能定位、备份迁移和常见故障处理,按实战场景而不是命令字典来组织。不管是刚接手Oracle环境的新手DBA,还是需要自己维护数据库的应用负责人,照着这套思路去敲,基本能解决大部分日常问题。
1. 环境连接与实例状态盘点,先搞清楚你连的是谁
1.1 连接数据库的几种姿势和验证手段
先说最基础的,sqlplus的登录方式我这么多年总结下来就四种,分别应对不同场景。
本地操作系统认证登录,主要用于服务器本机执行管理操作,尤其是实例异常、监听没起来的时候,这是唯一的入口:
bash复制sqlplus / as sysdba
这背后走的是操作系统级认证,不需要密码,本质上是利用了OS用户所属的dba组身份。只要你登录服务器的系统用户属于dba组,就能以sysdba身份进数据库。这套机制在实例半死不活、密码文件丢失时是救命通道。我有一次在客户现场遇到密码文件损坏,Oracle报ORA-01994,就是用这种方式进场恢复的。
远程管理用标准连接串,日常应用或者本机客户端连开发库比较常用:
bash复制sqlplus sys/oracle@192.168.1.100:1521/ORCL as sysdba
注意这里的格式是主机IP:端口/服务名,不是SID。很多新手分不清服务名和SID的差别,搞出ORA-12514。要查当前实例的SERVICE_NAME,可以直接用lsnrctl services命令看监听注册信息,或者进库后查v$active_services。
还有两种是运维脚本里常用的:操作系统用户切到oracle账后使用sqlplus /nolog先启动sqlplus,再通过connect命令连接,适合在shell脚本里根据条件动态选择登录账号;另一种是用环境变量组合,export ORACLE_SID=ORCL后直接sqlplus / as sysdba,适合多实例共存时快速切换。
进库后第一件事,我建议先执行验证语句:
sql复制select status from v$instance;
select name, open_mode from v$database;
select instance_name, host_name, version, startup_time from v$instance;
v$instance的status显示OPEN才代表数据库对外正常服务,如果是STARTED或MOUNTED,说明实例起来了但数据库还没打开,对外连接会失败。v$database的open_mode很直观,READ WRITE是正常,READ ONLY是只读,如果看到MOUNTED,那就得想想是不是有人做过shutdown或者恢复操作没做完。
1.2 关键配置参数查询,别靠记忆硬扛
刚接手一套陌生环境,与其问前一个人这个库怎么配的,不如自己敲命令摸清底细。我常用的有这几条:
sql复制-- 查看数据库所有基础参数
show parameter db_block_size;
show parameter processes;
show parameter sessions;
show parameter sga_target;
show parameter pga_aggregate_target;
show parameter db_recovery_file_dest;
show parameter db_recovery_file_dest_size;
show parameter log_archive_dest;
show parameter compatible;
show parameter control_files;
show parameter模糊匹配变量名很方便,但真实生产环境我更喜欢从v$parameter视图拿更完整的信息,尤其是确认哪些参数是spfile里的非默认值:
sql复制select name, value, isdefault, ismodified
from v$parameter
where ismodified != 'FALSE'
order by name;
这条SQL能直接告诉你当前实例哪些参数被人手工改过,是排查性能问题和复盘变更记录的好帮手。另外compatible参数特别值得关注,它决定了数据库特性开关的级别。比如12c的库如果compatible设置成11.2.0.4,那很多12c的新特性根本用不了,不是版本不够,是参数没放开。
还有控制文件路径也别忽略,一旦控制文件所在的盘出问题,连库都mount不上:
sql复制show parameter control_files;
我真实遇到过客户迁移数据文件时只搬了数据文件,没搬控制文件,结果启动报错ORA-00205。后来就是用show parameter control_files确认了路径,再用alter system set control_files=... scope=spfile修正的。
1.3 监听器的日常维护命令
监听器是数据库对外的"总机",连不上的时候十有八九是它出了问题。Linux下切换到oracle用户,最常见的就是这组:
bash复制lsnrctl status
lsnrctl start
lsnrctl stop
lsnrctl services
lsnrctl status会显示监听端口、主机名、实例注册情况。我最在意的就是最后面几行,比如ORCL这个实例是否已注册,注册的SERVICE_NAME是什么,状态是READY还是BLOCKED还是UNKNOWN。如果实例注册成UNKNOWN,说明是静态注册,通常是listener.ora里写了静态条目。如果看到实例没注册上去,优先查两个东西:实例是否真的起来了,还有local_listener参数对不对。
bash复制lsnrctl set log_status off
lsnrctl trace off
这两条是监听排障时必用的,一个关闭监听日志防止测试期间日志暴涨,一个关掉跟踪。生产上我一般不轻易开trace,开了容易把磁盘写满。
监听器最重要的排查场景是"客户端能ping通IP但连不上数据库"。我的排查顺序稳定是三步:第一步确认主机端口通不通,telnet 192.168.1.100 1521;第二步看监听状态里实例在不在;第三步查数据库实例是否OPEN。这几个顺序反了容易白折腾半天,我就见过有人盯着listener.ora改了半天,结果数据库根本没开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 存储与表空间管理:容量问题的核心战场
2.1 表空间创建与扩容的实战操作
表空间是Oracle逻辑存储的核心,对应到物理上就是数据文件。日常运维中90%的存储问题集中在表空间不足,也就是ORA-01653之类的报错。创建表空间的标准语句长这样:
sql复制create tablespace TS_APP
datafile '/u01/app/oracle/oradata/ORCL/ts_app01.dbf'
size 8G
autoextend on
next 1G
maxsize 32G
extent management local
segment space management auto;
几个关键点在autoextend on和next 1G。开启自动扩展后,文件用完会自动增加1G,省得天天盯着告警。但生产环境我建议谨慎开自动扩展,或者至少设置maxsize上限,防止数据异常膨胀把整个磁盘写满。另外extent management local和segment space management auto是现在的主流配置,本地管理表空间配合自动段空间管理,能有效避免碎片问题。
表空间不够用的时候,扩容有两条路:把已有数据文件调大,或者新增数据文件。
sql复制-- 方式一:调整已有数据文件大小
alter database datafile '/u01/app/oracle/oradata/ORCL/ts_app01.dbf' resize 16G;
-- 方式二:新增数据文件
alter tablespace TS_APP add datafile '/u01/app/oracle/oradata/ORCL/ts_app02.dbf' size 8G autoextend on maxsize 32G;
生产环境我优先选择新增数据文件,原因很简单:resize已有文件会触发文件内部的重组,高峰期可能带来额外IO压力,而新增文件相当于给表空间加了个新房间,重新分配空间更平滑。当然如果表空间里单个段太大,需要连续大块空间,那还是resize更合适。
2.2 空间使用率与单表大小的查询脚本
光会扩容没用,得知道空间到底哪去了。我每次巡检必查的就是空间使用率:
sql复制select b.tablespace_name,
round(b.bytes/1024/1024/1024, 2) total_gb,
round((b.bytes - nvl(a.bytes, 0))/1024/1024/1024, 2) used_gb,
round(nvl(a.bytes, 0)/1024/1024/1024, 2) free_gb,
round((1 - nvl(a.bytes, 0)/b.bytes)*100, 2) used_pct
from (select tablespace_name, sum(bytes) bytes
from dba_data_files group by tablespace_name) b
left join (select tablespace_name, sum(bytes) bytes
from dba_free_space group by tablespace_name) a
on b.tablespace_name = a.tablespace_name
order by used_pct desc;
这个脚本会一次性列出所有表空间的总大小、已用、剩余和使用百分比。注意dba_free_space查的是连续空闲空间,不是总空闲量的简单累加,所以如果表空间碎片化严重,即使剩余空间足够,也可能因为找不到足够大的连续空间而报错。
数据文件层面可以查v$datafile,但真正定位哪个表占空间比较多,要用下面的语句:
sql复制select owner,
segment_name,
segment_type,
round(bytes/1024/1024/1024, 2) size_gb,
tablespace_name
from dba_segments
where owner = 'APP'
order by bytes desc
fetch first 20 rows only;
有次客户反馈某个业务表空间暴涨,我用这条SQL定位到是一个中间表积累了几百G的临时数据,应用侧没有定期清理。找到元凶后就好办了,业务方确认后直接truncate,空间马上释放。所以不管表象多吓人,先查dba_segments定位大头,永远比瞎猜快。
2.3 undo表空间与临时表空间的监控命令
undo和临时表空间属于特殊类型,日常监控容易被忽略,但恰恰是它们最容易引发ORA-01555和ORA-01652这种经典错误。
undo表空间使用率查询:
sql复制select tablespace_name, status, sum(bytes)/1024/1024 mb
from dba_undo_extents
group by tablespace_name, status;
status为ACTIVE表示当前正在使用的事务回滚段,UNEXPIRED表示事务已提交但还没到undo_retention时间,EXPIRED表示过期可以覆盖。正常情况ACTIVE占比不高,如果ACTIVE持续高涨,要么是有长事务没提交,要么是undo太小且retention设得太大。
临时表空间监控主要看当前使用量和峰值:
sql复制select tablespace_name, current_bytes/1024/1024 current_mb,
max_used_bytes/1024/1024 max_used_mb
from v$temp_space_header;
-- 临时表空间使用率(含排序等操作占用的临时段)
select tablespace_name, sum(bytes_used)/1024/1024 used_mb,
sum(bytes_free)/1024/1024 free_mb
from v$temp_extent_pool
group by tablespace_name;
临时表空间经常出现"明明没多少数据却占用很高"的情况,这通常是大排序、大哈希连接或者索引重建导致的。处理办法是临时表空间可以安全重启清空,重启实例后临时段全部释放。但要注意临时文件路径如果有问题会导致实例起不来,所以清空前务必确认临时文件存在且权限正确。
临时表空间的重建命令,我分享一套比较完整的流程:
sql复制-- 新增一个临时表空间
create temporary tablespace TEMP_NEW
tempfile '/u01/app/oracle/oradata/ORCL/temp_new01.dbf'
size 4G autoextend on maxsize 32G;
-- 切换默认临时表空间
alter database default temporary tablespace TEMP_NEW;
-- 删除旧临时表空间
drop tablespace TEMP including contents;
这个流程在"临时表空间碎片化严重导致排序性能差"的时候很管用,因为临时表空间无法像永久表空间那样单独整理碎片,重建是最干脆的方式。
3. 用户、权限与合规审计命令
3.1 用户创建与基础资源限制
用户管理是DBA权限控制的核心环节,等保测评查得最多的也是这块。创建用户的基础命令:
sql复制create user app_user identified by "Passw0rd#123"
default tablespace TS_APP
temporary tablespace TEMP
profile default
quota unlimited on TS_APP;
密码建议用双引号括起来,避免特殊字符被解析出问题。default tablespace指定用户默认存放对象的表空间,quota很关键,如果用户在表空间上没有配额,即使表空间有足够空间,建表也会报ORA-01950。生产环境DBA账号一般给unlimited配额,普通业务账号应该按需分配,这算是最基本的最小权限原则。
修改用户密码、锁定、解锁,也是高频操作:
sql复制alter user app_user identified by "NewPass#456";
alter user app_user account lock;
alter user app_user account unlock;
3.2 权限和角色,最小授权的实践
Oracle的权限体系很庞大,系统权限几百种,对象权限更多。新手最常见的错误是一上来就给grant dba to user,图省事,但这是安全大忌,等保测评查出来直接不合格。
我总结了一套日常授权的最小集合:
sql复制-- 给业务账号常用权限,但绝不轻易给DBA角色
grant connect, resource to app_user;
grant create session to app_user;
grant select, insert, update, delete on schemaA.table1 to app_user;
grant execute on schemaA.proc1 to app_user;
connect和resource在Oracle里其实是角色,连DBA都算不上,但它们能覆盖绝大多数应用连接和开发需求。更重要的是明确对象级授权,让app账号只能操作自己该操作的表和存储过程。
查看一个用户拥有哪些权限,用下面的语句:
sql复制-- 用户被授予的系统权限
select * from dba_sys_privs where grantee = 'APP_USER';
-- 角色权限
select * from dba_role_privs where grantee = 'APP_USER';
-- 对象权限
select * from dba_tab_privs where owner = 'APP_USER' or grantee = 'APP_USER';
如果一个账号到底能不能做某个操作说不清楚,用privilege视图一层层查,比瞎试快得多。回收权限时用revoke,注意revoke的语法需要指定具体权限类型,比如:
sql复制revoke select on schemaA.table1 from app_user;
3.3 等保合规相关的审计命令
现在等保测评已经成为DBA躲不开的工作项,Oracle层面的审计命令是必考科目。传统审计是细粒度审计的基础,开关命令如下:
sql复制-- 开启数据库审计
alter system set audit_trail = DB, EXTENDED scope=spfile;
-- 审计特定行为:登录
audit create session;
-- 审计授权行为
audit grant any privilege;
-- 审计DML操作(按用户)
audit insert, update, delete on app_user.business_table by access;
audit_trail设置为DB,EXTENDED表示审计记录写入数据库的aud$表,同时记录SQL文本和绑定变量。生产环境不建议开OS级别的审计,审计文件爆炸起来比数据库本身还难处理。设置成DB后,查询审计记录:
sql复制select os_username, username, action_name, timestamp, sql_text
from dba_audit_trail
where timestamp > sysdate - 1
order by timestamp desc;
12c及以上版本推荐统一审计,功能更细,性能开销更低。开启统一审计:
sql复制-- 查看是否已经启用统一审计
select * from v$option where parameter = 'Unified Auditing';
-- 创建统一审计策略
create audit policy audit_pol_ddl actions create table, drop table;
-- 启用策略
audit policy audit_pol_ddl;
统一审计的日志查起来和传统审计不一样,要走统一审计视图:
sql复制select event_timestamp, dbusername, action_name, object_name, sql_text
from unified_audit_trail
where event_timestamp > systimestamp - 1
order by event_timestamp desc;
我给客户做等保整改时,一般建议数据库层面只审四类动作:登录、DDL变更、权限授予和关键表DML。把审计粒度控制在"够用"而不是"全量",否则审计表膨胀比业务表还快。
4. 性能排查与常用SQL关键时刻
4.1 会话、等待事件与阻塞锁定位
数据库卡了,业务报"跑不动",这是DBA最常遇到的求助场景。我的排查逻辑是先看有没有阻塞,再看等待事件,最后抓SQL。
查当前所有会话及其状态:
sql复制select sid, serial#, username, status, sql_id,
event, wait_class, seconds_in_wait, blocking_session
from v$session
where username is not null
order by seconds_in_wait desc;
这条SQL几乎是我每个性能工单的第一步。blocking_session如果有值,说明这个会话正在被其他会话阻塞,顺着blocking_session的SID就能找到元凶。等保和性能排查里,锁等待是最常见的问题根源。
生产环境出现大量阻塞,优先定位"谁锁了谁",用这条:
sql复制select s1.sid waiting_sid,
s2.sid holding_sid,
s2.username holding_user,
s2.sql_id holding_sql_id,
s1.event
from v$session s1, v$session s2
where s1.blocking_session = s2.sid
and s1.blocking_session > 1;
找到持有会话后,可以看它正在执行的SQL是什么。如果确认是异常会话,需要杀掉:
sql复制alter system kill session '123,456' immediate;
注意'sid,serial#',serial#必须带上,否则可能杀错会话。加上immediate是快速终止,不等待事务回滚完成。生产上如果杀不掉,还要查OS层面的进程号配合kill -9,但那是最后的办法,优先用alter system。
4.2 分页、递归查询与条件优化SQL
Oracle的常用SQL约定俗成,但有几个点在面试和实际开发中被反复问,属于DBA必须张口就来的内容。
分页查询最有代表性,Oracle没有MySQL的limit,用的是rownum,但正宗的分页写法是配合子查询:
sql复制select *
from (select t.*, rownum rn
from (select * from app_user.big_table order by create_time desc) t
where rownum <= 40)
where rn > 20;
这里有个性能细节:最内层子查询的排序不能省,否则分页的结果是乱序的。11g开始Oracle支持offset...fetch,写法更优雅:
sql复制select * from app_user.big_table
order by create_time desc
offset 20 rows fetch next 20 rows only;
递归查询connect by start with是Oracle的招牌功能,典型场景是查树形结构,比如组织架构,比如BOM清单:
sql复制select emp_name, manager_id, level
from employees
start with emp_id = 1
connect by prior emp_id = manager_id;
start with指定起点,connect by prior定义父子关系,level是系统伪列表示层级深度。实际使用要特别注意循环引用问题,比如数据里存在"自己管理自己"的脏数据,不加nocycle会死循环。安全的写法是在connect by后面加nocycle:
sql复制select emp_name, manager_id, level
from employees
start with emp_id = 1
connect by nocycle prior emp_id = manager_id;
not exists的用法也是老生常谈但高频踩坑的,它和not in的区别在性能上尤其关键:
sql复制-- 正确的反连接写法,注意处理NULL
select *
from app_user.orders o
where not exists (select 1 from app_user.paid_orders p where p.order_id = o.order_id);
not in在做子查询时如果子查询结果包含NULL,会出现"一个都不返回"的问题;而not exists直接走反连接,性能也稳定很多。所以用Oracle不管是写业务还是做数据治理,能用not exists就别用not in。
trunc(sysdate)是处理日期条件时的高频函数,作用是去掉时间部分。常用的场景是"查今天的数据":
sql复制select * from app_user.orders
where create_time >= trunc(sysdate)
and create_time < trunc(sysdate) + 1;
用>=和<而不是between,可以避免边界漏数据,而且这个写法能走索引,比to_char(create_time, 'yyyy-mm-dd') = '2025-01-01'高效很多。后者的索引利用率几乎为零,我在优化SQL时见到一次改一次。
4.3 AWR报告与SQL执行计划的实用姿势
性能排查绕不开AWR。AWR报告相当于数据库在一段时间内的"体检报告",集中展示了CPU、IO、等待事件、SQL排行等核心数据。
生成AWR报告最常用的方式:
sql复制-- 手动生成快照,再做报告
exec dbms_workload_repository.create_snapshot();
exec dbms_workload_repository.create_report(
dbid => 1234567890,
begin_snap => 100,
end_snap => 101,
report_type => 'html',
report_name => '/tmp/awr.html');
不过实际工作中更常用的是从statspack和awrrpt脚本直接生成:
bash复制sqlplus / as sysdba
SQL> @?/rdbms/admin/awrrpt.sql
这个脚本会交互式问报告类型、天数、快照区间,适合不想记函数签名的场景。生成的HTML报告里,我要看的核心部分依次是:Top 10 Foreground Events by Total Wait Time、SQL Ordered by Elapsed Time、Instance Activity Stats。如果Top等待事件是db file sequential read,多半是SQL走了大量单块读;如果是log file sync,重点查提交频率和应用端批量提交是否有问题。
SQL执行计划,老规矩用explain plan加dbms_xplan两个命令:
sql复制explain plan for
select * from app_user.orders where create_time >= trunc(sysdate);
select * from table(dbms_xplan.display());
从执行计划能直观看到SQL是否走了全表扫描、是否有效利用索引、有没有排序、有没有哈希连接。我优化慢SQL时,第一眼先看有没有全表扫描,第二眼看谓词列有没有被函数包裹导致索引失效,第三眼看连接顺序是否合理。90%的SQL性能问题都能在这三步里找到答案。
5. 备份迁移与恢复场景命令
5.1 expdp/impdp逻辑备份与迁移
数据泵是Oracle做逻辑备份和跨环境数据迁移的主力工具,比老的exp/imp功能强太多。expdp导出的基本用法:
bash复制expdp system/oracle@ORCL directory=DATA_PUMP_DIR dumpfile=app_export.dmp logfile=export.log schemas=APP_USER parallel=4
directory必须指向数据库里已创建的directory对象,否则报ORA-39002。查看现有目录对象:
sql复制select * from dba_directories;
如果没有现成的,就创建一个:
sql复制create directory DATA_PUMP_DIR as '/u01/backup/dump';
导入端impdp的用法更灵活,支持带条件导入和表空间/用户映射:
bash复制impdp system/oracle@ORCL directory=DATA_PUMP_DIR dumpfile=app_export.dmp logfile=import.log schemas=APP_USER remap_schema=APP_USER:APP_USER_NEW remap_tablespace=TS_APP:TS_APP_NEW transform=segment_attributes:n table_exists_action=replace
remap_schema和remap_tablespace在环境迁移时几乎是必用的,因为源端和目标端的用户和表空间大概率不一样。table_exists_action=replace表示目标表已存在就替换,适合有变更重建的场景,但要注意它实际是先drop再create再导入,数据会有一小段空窗期。
真实项目里用expdp/impdp做表级别迁移也很常见,比如把一个几亿行的大表拆到历史库:
bash复制expdp system/oracle@ORCL directory=DATA_PUMP_DIR dumpfile=orders_2024.dmp logfile=export_orders.log tables=APP_USER.ORDERS query='"where create_time < trunc(sysdate, ''yyyy'')"' parallel=8
注意Linux下query参数外面要加单引号,里面SQL的引号要转义,这里很容易踩坑。
5.2 11g数据库冷迁移完整步骤
关于冷迁移,热搜词里也有人专门搜"oracle 11g 数据库怎么冷迁移",确实在实际工作中很实用。冷迁移的意思是把数据库停下来,直接把物理文件拷贝到新机器。相比RMAN,冷迁移的优势是简单直接,不依赖恢复流程,适合停机窗口充足的场景。
前提条件:新旧两台机器操作系统和数据库版本尽量一致,字符集保持一致。完整步骤我拆一下:
第一步,关闭数据库实例:
bash复制sqlplus / as sysdba
SQL> shutdown immediate;
shutdown immediate会等待当前事务回滚完成再关闭,如果事务非常大,回滚时间可能很长,但比shutdown abort安全得多。除非数据库已经挂死不响应,否则都不用abort。
第二步,确认需要拷贝的文件清单。核心就三类:数据文件、控制文件、在线重做日志。查一下路径:
sql复制select name from v$datafile;
select name from v$controlfile;
select member from v$logfile;
还有参数文件,一般就是$ORACLE_HOME/dbs/initORCL.ora或spfileORCL.ora,以及密码文件orapwORCL。
第三步,把整个Oracle目录(至少是参数文件、数据文件、控制文件、redo日志、密码文件)用scp或rsync拷贝到新机器。生产库数据量大的时候,用rsync比scp更适合断点续传:
bash复制rsync -avz /u01/app/oracle/oradata/ORCL/ oracle@新机器IP:/u01/app/oracle/oradata/ORCL/
第四步,新机器上配置好环境变量ORACLE_SID和ORACLE_HOME,更改文件属主为oracle用户,然后启动实例:
bash复制export ORACLE_SID=ORCL
sqlplus / as sysdba
SQL> startup;
如果控制文件路径和数据文件路径变了,startup会报错,这时要用alter database rename file修正控制文件里的路径信息,然后alter system set control_files=... scope=spfile,再重启。冷迁移有个老生常谈但必须提醒的点:源库shutdown之前务必检查归档模式和相关后台进程,冷迁移一般适用于非归档或者可以接受完全停机的情况,操作过程中所有文件一定要整体拷贝,缺一个redo日志就会出现无法open的情况。
5.3 归档模式与RMAN基础命令
归档模式直接决定数据库能否做在线热备和基于时间点的恢复。查看归档状态:
sql复制archive log list;
如果看到Database log mode: Archive Mode,就是正常归档模式。如果是No Archive Mode,生产环境建议立即开启。开启/切换归档模式:
bash复制sqlplus / as sysdba
SQL> shutdown immediate;
SQL> startup mount;
SQL> alter database archivelog;
SQL> alter database open;
注意归档模式必须在mount状态修改。改成归档后,查看归档日志的路径和占用空间也很关键:
sql复制select name, first_time, next_time from v$archived_log order by first_time desc;
-- 查看闪回恢复区使用率
select * from v$recovery_file_dest;
-- 查看闪回恢复区里文件占用
select file_type, percent_space_used from v$flash_recovery_area_usage;
归档日志把磁盘写满是我遇到过的最高频故障之一。解决办法是及时清理过期归档,可以用RMAN删除:
bash复制rman target /
RMAN> delete noprompt archivelog all completed before 'sysdate - 7';
这条命令保留最近7天归档,删除更早的。注意delete noprompt是自动确认,执行前最好先带report obsolete或者不带noprompt预览一下,防止误删。
RMAN基础备份命令,日常增量备份策略一般是0级全备加增量:
bash复制rman target /
RMAN> backup database plus archivelog delete input;
RMAN> backup incremental level 1 database;
RMAN还有校验和恢复验证的命令,我每次备份完都会做一次validate:
bash复制RMAN> restore database validate;
RMAN> backup validate check logical database;
backup validate check logical database不产生实际备份文件,而是验证所有数据文件和控制文件是否可读、逻辑是否一致。这是我在大版本升级前必做的一道安全作业,相当于给数据库做一次全方位的"安全体检"。
6. DBA常见故障排查速查
6.1 ORA-01653、ORA-01555等经典错误排查
下面这些问题基本是DBA日常最容易撞上的,我按报错号列了一个快速排查思路。
ORA-01653:表空间无法扩展。意思是数据文件不够大且无法自动扩展。第一反应是查空间使用率和autoextend状态,确认数据文件是否已经达到maxsize上限。如果达到上限,扩容方式就是增加数据文件或者把maxsize调大。还有一种特殊情况:文件系统磁盘满了,即使表空间参数没问题也扩展不了,这时候用df -h确认下磁盘剩余空间。
ORA-01555:快照太旧。这个报错在长查询和undo表空间不足时高频出现。本质上是一个查询需要读取某行的历史版本,而undo里对应的版本已经被覆盖。解决方向有四个:增大undo表空间、延长undo_retention参数、优化SQL缩短查询时间、把大查询拆成小批次。核心原则是不要让长查询和频繁更新大表同时发生。
ORA-01652:临时表空间无法分配临时段。常见于大排序或者大索引重建。排查思路:先查v$temp_space_header确认临时表空间使用率,再加大临时文件或者重建临时表空间。还有一种隐藏情况是临时表空间路径所在磁盘满了,跟ORA-01653一样要检查文件系统。
ORA-12514:监听器不认识服务名。排查步骤是先确认客户端连接串里的服务名和监听器注册的SERVICE_NAME是否一致。lsnrctl services能直接看到注册的服务名,然后核对连接串。如果服务名不匹配,改连接串,或者在listener.ora里加静态注册。
ORA-01555的排查脚本我一般这样用:
sql复制-- 查看undo retention设置
show parameter undo_retention;
-- 查看undo表空间大小和自动扩展状态
select tablespace_name, file_name, autoextensible, bytes/1024/1024 mb
from dba_data_files
where tablespace_name like 'UNDO%';
先确认参数和空间,再判断是否需要优化SQL,顺序不能反。
6.2 12c删除不干净的重装问题处理
热搜里有"12c删除不干净",这确实是12c常见的重装痛点。很多人卸载12c后,重新安装时报错,或者旧实例还在,装完了起不来。原因往往是残留的服务、目录和初始化参数文件。
Linux环境下的清理思路,我总结成五步:
第一步,停掉所有相关进程和监听:
bash复制lsnrctl stop
sqlplus / as sysdba
SQL> shutdown abort;
如果实例已经起不来,shutdown abort可能也会卡住,这时候直接杀掉后台进程:
bash复制ps -ef | grep ora_ | grep -v grep | awk '{print $2}' | xargs kill -9
第二步,删除/etc/oratab里对应的条目,避免默认环境变量被污染。
第三步,删除ORACLE_HOME整个目录:
bash复制rm -rf /u01/app/oracle/product/12.2.0/dbhome_1
rm -rf前一定要再三确认路径,这是DBA的生死线。我建议rm之前先用ls -ld看一下目录是不是oracle安装目录,避免手滑把数据目录删了。
第四步,清理/etc/oraInst.loc和/opt/ORCLfmap等安装配置文件。12c之后还要检查/u01/app/oraInventory里的inventory信息,重装时如果inventory残留,安装程序会认为Oracle已经装过,导致无法继续。
第五步,清理数据库文件目录。如果确认数据全部不需要,就删掉/u01/app/oracle/oradata/ORCL整个目录。如果数据还有用,重装前务必备份完整的oradata目录。
等所有这些清理完,再重启系统或者重新打开一个终端,确认环境变量没有残留的ORACLE_HOME,然后重新执行安装程序。12c的安装日志在/u01/app/oraInventory/logs下,如果安装报错,第一个动作就是看这个日志目录下的installActions*.log,大部分问题都能在日志里找到具体原因。
6.3 CLOB、dual等日常细节操作
一些小细节在实际操作中很容易让人卡壳,比如CLOB字段的查询和更新。CLOB在sqlplus里默认显示不完整,拼接时也不能直接相加。我常用的处理:
sql复制-- 查看CLOB字段长度
select dbms_lob.getlength(content) len from app_user.documents where id = 1;
-- 更新CLOB字段,注意使用to_clob
update app_user.documents
set content = to_clob('新的内容,可以是很长的文本...')
where id = 1;
commit;
-- 查询CLOB前100个字符
select dbms_lob.substr(content, 100, 1) from app_user.documents where id = 1;
CLOB更新时如果内容很长,超过4000字符,直接用字符串常量会报ORA-01704。这时候要用to_clob拼接多个字符串或者用存储过程里的dbms_lob.append来处理。这是很多开发者第一次遇到CLOB写不进去的原因。
dual表也是Oracle的一个经典细节。dual是Oracle自带的一个单行单列表,常用来做无表查询。有人会问"dual最多能存多大",其实它本身没有存储意义,它就一个虚拟表,行数永远只有一行,字段就一个dummy,类型varchar2(1),值通常为X。所以dual不存在"存多大"的问题,它只是一个语法占位符。比如:
sql复制select sysdate from dual;
select 'hello' from dual;
dual在查询中主要用来输出常量、计算表达式、调用函数,不需要关联任何业务表。
另外提醒一句,操作CLOB、大字段和表结构变更时,尽量在业务低峰期进行,并且提前备份,这类DDL一旦锁表,影响范围往往比预想的大得多。我在处理大表加字段时,即使Oracle 11g及以上已经支持默认值快速添加,遇到带默认值且非空的情况,还是要评估数据字典更新的成本,不能想当然。
最后再分享两个小技巧
第一,养成"动手前先查脚本"的习惯。很多DBA老手不是命令背得比新手多,而是他们把常用的命令都写成了脚本文件,分类放在服务器上,用的时候直接调用。我自己维护了一个dba_toolkit目录,下面有tablespace.sql、session_locks.sql、awr_gen.sh、rman_backup.sh这类脚本,每次到了新环境,先把基础配置的脚本传上去,后面排查效率会高很多。
第二,操作数据库前,尤其是批量修改、删数据、迁移割接,务必先做两件事:确认当前时间窗口内没有关键批处理任务,以及确认自己已经执行过至少一次备份。哪怕只是删一条生产数据,也要先备份目标表,用create table xxx_bak_20250101 as select * from xxx做一份快速备份,成本很低,但能避免很多灾难性后果。
Oracle的命令体系说多也多,说少也少,核心就是连接、存储、权限、性能、备份恢复这五大块。真正到了生产环境,你会发现能救场的往往不是多么冷门的命令,而是对常用命令的熟练度和对报错信息的敏感度。希望这组整理对正在做DBA或者即将走上这个岗位的朋友有帮助。
