Oracle常用维护操作

一、前言

首先声明我不是一名DBA,文档中有不准确的地方欢迎大家指出。至于我为什么写这篇文章,主要是对平时工作中的总结,你可能会问我“你们公司或部门没有DBA吗?” 肯定有啊,不过DBA在我们公司是稀缺资源,一百多号人中才有一个DBA,不是什么要紧的事,根本叫不动他们!项目经理也没办法,一些活只能自己搞!

二、Oracle常用维护操作

1.启动、停止数据库

# 启动
su - oracle
sqlplus / as sysdba;
SQL>startup;

# 停止
su - oracle
sqlplus / as sysdba;
SQL>shutdown immediate;

2.启动、停止监听

# 启动
su - oracle
lsnrctl start
lsnrctl status

# 停止
su - oracle
snrctl stop
lsnrctl status

说明:监听器每隔几分钟动态注册,若执行查看监听器状态无对应数据库实例,可尝试手动注册。

sqlplus / as sysdba
SQL>alter system register;

3.IP白名单

  • 单节点
su - oracle
cd $ORACLE_HOEM/network/admin/
# 查看是否存在sqlnet.ora文件及是否已配置tcp.validnode_checking、tcp.invited_nodes、tcp.excluded_nodes项。如果文件存在且已有这几项,则在此基础上修改这几项;如果文件存在但这几项不存在,则在最后追加;如果文件不存在则直接新建。

vim sqlnet.ora
# 追加以下内容:
tcp.validnode_checking=yes
tcp.invited_nodes=(127.0.0.1,自身IP,192.168.1.128,192.168.1.129)
tcp.excluded_nodes=(192.168.1.242)
lsnrctl reload

注意:一定要添加自身所有IP,否则监听器状态可能会看不数据库实例注册到监听器。

说明

tcp.validnode_checking–此项是启用IP合法检查,此项是必须配置的,如果不启用其他两项配了也没用
tcp.invited_nodes–此项是允许连接数据库的IP地址,多个地址用逗号(半角)隔开;如果启用此项,一定要配上本地地址不然监听无法启动。
tcp.excluded_nodes–此项是不允许连接数据库的IP地址,多个地址用逗号(半角)隔开;如果与tcp.invited_nodes有相同IP,则还是允许该IP访问数据库
tcp.invited_nodes和tcp.excluded_nodes其实可以只配置一项,当只配tcp.invited_nodes时就是白名单,在此项列表中的所有IP允许访问数据库,所有不在此项列表中的所有IP拒绝访问数据库;
当只配置tcp.excluded_nodes时,在此项列表中的所有IP拒绝访问数据库,所有不在此项列表中的所有IP允许访问数据库。

  • RAC集群
# 备份和恢复oracle ini初始化文件,防止配置错误或其它原因导致的服务不可用
su - oracle
# 备份
SQL>create pifle='/home/backup/pfile20200920.ora' from spfile;
# 恢复
SQL>create spfile from pifle='/home/backup/pfile20200920.ora' ;

说明:spfile作用域memory、spfile、both(默认);修改内存、CPU、连接数等初始化参数时,强烈建议备份spfile

su - grid
$GRID_HOME/NETWORK/ADMIN
vim sqlnet.ora
# 追加以下内容:
tcp.validnode_checking=yes
tcp.invited_nodes=(127.0.0.1,private IP,scan ip,virual IP,192.168.1.128,192.168.1.129)
tcp.excluded_nodes=(192.168.1.242)
# 执行以下命令重新加载监听器配置,等待几分钟(期间监听器对外服务不可用,建议一个一个节点执行,防止期间数据库无法访问)。
lsnrctl reload

说明

  • ORACLE用户下的 O R A C L E H O M E / N E T W O R K / A D M I N 目 录 下 没 有 s q l n e t . o r a 文 件 , 必 须 使 用 G U I D 用 户 登 录 进 入 ORACLE_HOME/NETWORK/ADMIN目录下没有sqlnet.ora文件,必须使用GUID用户登录进入 ORACLEHOME/NETWORK/ADMINsqlnet.ora使GUIDGRID_HOME/NETWORK/ADMIN下的sqlnet.ora文件,添加修改。

  • 添加白名单时必须添加本地IP,因为是RAC环境,必须把连个节的真实IP,私有IP,VIP,SCAN IP全部添加进白名单。

  • 每个节点都要按此操作执行。

4.密码过期

su - oracle
sqlplus / as sysdba
SQL>SELECT * FROM dba_profiles s WHERE s.profile=\'DEFAULT\' AND resource_name=\'PASSWORD_LIFE_TIME\';
SQL>ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
SQL>alter user scott identified by tiger;

5.数据泵导入、导出

(1)手动创建数据泵导出目录**(可选)**

su - oracle
mkdir sdir
sqlplus / as sysdba
SQL>create directory DATA_PUMP_DIR_SCOTT as '/home/oracle/sdir';
SQL>grant read,write on directory DATA_PUMP_DIR_SCOTT to scott;
SQL> exit

(2)导出

# 查看默认的数据泵导出目录(DATA_PUMP_DIR),并记录下来。
su - oracle
sqlplus / as sysdba
SQL>select * from dba_directories;
SQL> exit
expdp SCOTT/SCOTT directory=DATA_PUMP_DIR dumpfile=scott20200920.dmp schemas=SCOTT

(3)创建表空间、用户、授权

SQL>CREATE TEMPORARY TABLESPACE SCOTT_TEMP TEMPFILE 'D:\app\oracle\data\SCOTT_TEMP.DBF'  size 2048M autoextend on next 50M maxsize 20480M EXTENT MANAGEMENT LOCAL;
SQL>create tablespace TBS_SCOTT_TEST datafile 'D:\app\oracle\data\TBS_SCOTT01.DBF' size 2048M autoextend on next 50M maxsize 20480M EXTENT MANAGEMENT LOCAL;
SQL>create user SCOTT_TEST identified by SCOTT_TEST default tablespace TBS_SCOTT_TEST TEMPORARY TABLESPACE SCOTT_TEMP;
SQL>GRANT CONNECT,RESOURCE TO SCOTT_TEST;
# 可选
SQL>grant all privileges to SCOTT_TEST;--除DBA权限之外的所有权限(可选)
SQL>GRANT DBA TO SCOTT_TEST;  --DBA权限(可选)

(4)导入

impdp SCOTT_TEST/SCOTT_TEST directory=DATA_PUMP_DIR dumpfile=scott20200920.dmp remap_schema=SCOTT:SCOTT_TEST remap_tablespace=TBS_SCOTT:TBS_SCOTT_TEST

说明:schema及tablespace和导出时不同的话,需指定remap_schema及remap_tablespace。

参照

Oracle数据泵

6.表空间使用情况(含临时表空间)

select * from ( 
Select a.tablespace_name, 
to_char(a.bytes/1024/1024,'99,999.999') total_bytes, 
to_char(b.bytes/1024/1024,'99,999.999') free_bytes, 
to_char(a.bytes/1024/1024 - b.bytes/1024/1024,'99,999.999') use_bytes, 
to_char((1 - b.bytes/a.bytes)*100,'99.99') || '%' use 
from (select tablespace_name, 
sum(bytes) bytes 
from dba_data_files 
group by tablespace_name) a, 
(select tablespace_name, 
sum(bytes) bytes 
from dba_free_space 
group by tablespace_name) b 
where a.tablespace_name = b.tablespace_name 
union all 
select c.tablespace_name, 
to_char(c.bytes/1024/1024,'99,999.999') total_bytes, 
to_char( (c.bytes-d.bytes_used)/1024/1024,'99,999.999') free_bytes, 
to_char(d.bytes_used/1024/1024,'99,999.999') use_bytes, 
to_char(d.bytes_used*100/c.bytes,'99.99') || '%' use 
from 
(select tablespace_name,sum(bytes) bytes 
from dba_temp_files group by tablespace_name) c, 
(select tablespace_name,sum(bytes_cached) bytes_used 
from v$temp_extent_pool group by tablespace_name) d 
where c.tablespace_name = d.tablespace_name 
) ;

7.扩展表空间

# 查看数据文件位置
SQL>select name from v$datafile;
# 为指定表空间增加数据文件
SQL>ALTER TABLESPACE TBS_SCOTT ADD DATAFILE 'D:\app\oracle\data\TBS_SCOTT02.DBF' SIZE 20480M;

注意:Oracle RAC下采用grid盘,跟目录为“+”不可以省略。例如:“+/datagrid01/data/TBS_SCOTT02.dbf”

8.修改oracle最大连接数

# 备份和恢复oracle ini初始化文件,防止配置错误或其它原因导致的服务不可用
su - oracle
# 备份
SQL>create pifle='/home/backup/pfile20200920.ora' from spfile;
# 恢复
SQL>create spfile from pifle='/home/backup/pfile20200920.ora' ;
SQL>alter system set processes=1000 scope = spfile;

说明:sessions是个派生值,由processes的值决定,公式一般为sessions=1.1*process + 5,可不用设置。

9.手动释放锁

# 锁表情况
SQL>select object_name,machine,s.sid,s.serial#
from v$locked_object l,dba_objects o ,v$session s
where l.object_id = o.object_id and l.session_id=s.sid;

SQL>select S.sid,S.SERIAL# from v$session S where username='SCOTT';
SQL>alter system kill session 'sid,SERIAL'

说明:Oracle Linux版本,session是进程级别的,Windows版本是线程级别的。若Linux下使用以上命令仍不能彻底释放资源,可使用OS级别kill强制释放。

Linux:

SQL>select spid, osuser,s.program
from v$session s,v$process p
where s.paddr=p.addr and s.sid=24 (24是上面的sid)
SQL>exit
kill -9 12345(12345为上面查询出的spid)

windows:

orakill sid thread #分别为24 12345

10.统计信息状态查询及开启自动收集

-- 查询统计信息是否陈旧
SQL>select * from dba_tab_statistics order by last_analyzed desc;

介绍

Statistic对Oracle是非常重要的。它会收集数据库中对象的详细信息,并存储在相应的数据字典里。根据这些统计信息,optimizer可以对每个SQL去选择最好的执行计划。Oracle的Statistic信息的收集分两种:自动收集和手工收集。

参考

统计信息

自动收集

Oracle的自动维护任务

在oracle11g中,有个autotask的新特性,可以用来自动的收集优化信息,收集段信息等等。在EM中,我们看进菜单server-Oracle Scheduler-Automated Maintenance Tasks来看到他们:

自动收集任务

linux启动EM

emctl start dbconsole

访问地址:
http://localhost:1158/em

启用自动收集任务

  • 打开总开关

    --可查看SELECT * FROM SYS.DBA_AUTOTASK_TASK;是否有值,默认没有,开启后有值!
    begin
    dbms_auto_task_admin.enable();--或dbms_auto_task_admin.enable;
    end;
    
  • 打开指定维护窗口(默认周一到周日全部打开,可以选择性关闭)

    SELECT * FROM SYS.DBA_SCHEDULER_WINDOW;
    -- 打开
    dbms_scheduler.enable(name=>'SATURDAY_WINDOW');
    -- 关闭
    dbms_scheduler.disable(name=>'SATURDAY_WINDOW',froce=>true);
    
  • 执行历史查询

    SELECT * FROM SYS.DBA_AUTOTASK_JOB_HISTORY;
    SELECT * FROM SYS.DBA_AUTOTASK_CLIENT_HISTORY;
    

11.绑定变量

问题:大家可能遇到这样的问题,我们java代码中或mybatis xml中的一些SQL执行时很慢,而自己把SQL拿到sqldeveloper或者navicate一类的工具中执行很快,这是为什么?

可能原因: 要回答这个问题,首先要知道我们的代码中干了哪些操作。

  • 是否为分页SQL,分页SQL除了一个SELECT C1,C2 FROM 的SQL语句还有一个SELECT COUNT(0) FROM的SQL语句,而慢的往往是COUNT(0)
  • 是否进行变量绑定,注意是“变量绑定”,而不是"拼接符"(如Mybatis里的${})

“变量绑定”是什么?
bind variable: A variable in a SQL statement that must be replaced with a valid value, or the address of a value, in order for the statement to successfully execute.

变量绑定是OLTP系统中一个非常值得关注的技术。良好的变量绑定会使OLTP系统数据库中的SQL执行速度飞快,内存效率极高;不使用绑定变量可能会使OLTP 数据库不堪重负,资源被SQL解析严重耗尽,系统运行缓慢。当一个用户与数据库建立连接后,会向数据库发出操作请求,即向数据库送过去SQL语句。Oracle在接收到这些SQL后,会先对这个SQL做一个hash函数运算,得到一个Hash值,然后到共享池中寻找是否有和这个hash 值匹配的SQL存在。 如果找到了,Oracle将直接使用已经存在的SQL 的执行计划去执行当前的SQL,然后将结果返回给用户。 如果在共享池中没有找到相同Hash 值的SQL,oracle 会认为这是一条新的SQL。 会进行解析。

Oracle 解析的步骤如下:
(1)语法解析
(2)语义解析
(3)生成执行计划,这里分软解析和硬解析。硬解析是非常耗资源的。
(4)SQL的执行

再提一个问题,若使用“绑定变量”方式给参数赋值,SQL解析时一定会忽略变量吗?
关键字: “变量窥探” “SQL动态游标”

Bind Peeking是Oracle 9i中引入的新特性,它的作用就是在SQL语句硬分析的时候,查看一下当前SQL谓词的值,以便生成最佳的执行计划。

要想搞懂SQL的机制,不是一篇博客就可以讲清楚的,推荐大家看看这两本书!
《详细Oracle教程》:难度中(DBA必读、研发人员建议通读)
《Oracle核心技术%2B路易斯》:难度高(DBA建议通读)

举例:

SELECT * FROM DUAL WHERE '1' = :v1;
SELECT * FROM DUAL WHERE '1' = '1';

绑定变量

12.表分区

-- 按月分区,2018年以前数据归为分区P1
CREATE TABLE T_TEST
(
   TABLE_ID NUMBER(8),
   SUB_DATE DATE,
   VALUE NUMBER(8)
 
)
PARTITION BY RANGE(SUB_DATE)
INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
(
  PARTITION P1 VALUES LESS THAN(TO_DATE('2018-01-01','YYYY-MM-DD'))
);

--查看分区
SELECT * FROM USER_TAB_PARTITIONS WHERE TABLE_NAME=UPPER('T_TEST_PARTITION');

未完待续……

猜你喜欢

转载自blog.csdn.net/ory001/article/details/108715361