【Oracle】DBA日常管理工具手册

目录

基础知识

exp/imp使用原则

数据迁移

11gR2数据迁移到19c(字符集不同)

 问题手记

管理工具

数据库高可用调优

增加控制文件

增加重做日志文件

调整归档模式

调整闪回模式

调整闪回保留策略

调整控制文件备份策略

调整备份文件保留策略

日常自动化备份脚本

0级备份脚本

1级备份脚本

crontab设置自动执行备份

扩充varchar2和nvarchar2支持的最大字节


本文档主要面向有一定Oracle数据库操作经验的开发人员和运维人员,文档分两部分,第一部分是ORACLE的基础知识讲解只要对常用的一些数据库命令进行整理和讲解;第二部分则通过实际案例讲解实际工作中的一些最佳实践,来展示这些命令的实际运用。这些案例也可以作为一个DBA入门的操作指导手册。但是实际数据库环境和业务场景千差万别,切忌直接不假思索的套用本文档案例,任何在生产环境的实施都要经过严格的技术验证。

基础知识

exp/imp使用原则

在进行数据迁移,常用到exp/imp工具,该工具可以跨平台、版本。下面介绍下在使用不同版本的exp/imp时候的注意事项

官网说明如下

使用不同版本的exp/imp

无论在什么时候,在不同版本的oracle 数据库中迁移数据时,都必须要遵守如下的基本规则

1.  imp工具的版本必须和目标库的版本相同。例如,使用版本为

9.2.0.7的imp工具导入到版本为9.2.0.8的数据库中,会遇到错误。

2. exp工具的版本必须与源库或者目标库中版本较低的相同。

例如,从低版本的源库exp导出数据,imp导入到高本版目标库,那么exp的版本必须要和源库相同。同理,

从高版本的源库exp导出数据,imp导入到低版本目标库,那么exp的版本必须和目标库相同。

使用不同版本的exp/imp的约束

1. exp工具导出的dmp文件,只能用imp工具导入。也就是说exp/imp配对使用,expdp/impdp配对使用 。exp导出的dmp文件无法用impdp导入。

2. 任何exp导出的文件,都可以imp到高版本的数据库中。也就是说,exp/imp向下兼容。

3. 低版本的imp工具无法读取高版本的exp导出的文件。例如9.2 exp导出的dmp文件无法用9.0.1版本的imp工具导入。

字符集操作

【1】查看字符集

这个是创建数据库时就需要考虑好,一旦定下来,以后就不能随便更改,风险很大,最佳推荐使用AL32UTF8,需要关注的参数是常规字符集NLS_NCHAR_CHARACTERSET,国家字符集(用在NVARCHAR2类型)NLS_NCHAR_CHARACTERSET

#客户端字符集
SQL> select USERENV('LANGUAGE') from dual;

USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8
#服务端字符集
SQL> select PARAMETER,VALUE from NLS_DATABASE_PARAMETERS;

PARAMETER                      VALUE
------------------------------ ------------------------------
NLS_RDBMS_VERSION              19.0.0.0.0
NLS_NCHAR_CONV_EXCP            FALSE
NLS_LENGTH_SEMANTICS           BYTE
NLS_COMP                       BINARY
NLS_DUAL_CURRENCY              $
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZR
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_FORMAT                HH.MI.SSXFF AM
NLS_SORT                       BINARY
NLS_DATE_LANGUAGE              AMERICAN

PARAMETER                      VALUE
------------------------------ ------------------------------
NLS_DATE_FORMAT                DD-MON-RR
NLS_CALENDAR                   GREGORIAN
NLS_NUMERIC_CHARACTERS         .,
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_CHARACTERSET               AL32UTF8
NLS_ISO_CURRENCY               AMERICA
NLS_CURRENCY                   $
NLS_TERRITORY                  AMERICA
NLS_LANGUAGE                   AMERICAN

20 rows selected.

技术专题

上下文全文检索

权限要求:用sys用户给当前用户授予CTX_DDL,CTX_OUTPUT和CTX_DOC的execute权限。

CTXCAT索引

适用场景:短文本列

标准运算符:CATSEARCH

支持的逻辑运算符:

逻辑与:AND(空格) 

逻辑运算符
描述操作符同义符范例
AND空格

a b c

a AND b AND c

OR|

a|b|c

a OR b OR c

NOT-a - b注意是带空格的
字符串"...""a b c"整个字符串
分组()(a b)|c

特点:在更新基表的同时会更新索引,无需手动同步索引

创建语法:

create index <indexname> on <tablename>(<columnname>)
indextype is ctxsys.ctxcat
        parameters('...');

 parameters部分参数介绍:

1. index set(索引集)

#创建索引集语法:

ctx_ddl.create_index_set('<索引集名称>');
ctx_ddl.add_index('<索引集名称>','<索引字段>');

这是用在CATSEARCH第三个参数中复合查询条件中的字段建索引

2. section group(节组)

#创建节组语法

ctx_ddl.create_section_group('<节组名称>', 'BASIC_SECTION_GROUP'); ctx_ddl.add_field_section('<节组名称>','<节名称>','<标识名>');

这可以使 CTXCAT索引通过模板来用到CONTEXT索引的特性,如针对htmp,xml格式的文本

例子:
#创建索引集
exec ctx_ddl.create_index_set('BOOK_INDEX_SET'); 
exec ctx_ddl.add_index('BOOK_INDEX_SET','PUBDATE'); 
#创建节组
exec ctx_ddl.create_section_group('BOOK_SECTION_GROUP', 'BASIC_SECTION_GROUP'); exec ctx_ddl.add_field_section('BOOK_SECTION_GROUP','AUTHOR','AUTHOR'); 
exec ctx_ddl.add_field_section('BOOK_SECTION_GROUP','LANGUAGE','LANGUAGE');
#创建CTXCAT索引
create index books_index on books(info) indextype is ctxsys.ctxcat parameters('index set book_index_set section group book_section_group');

#查询,其中第二个参数是context的模板,里面用到了within运算符,author和language是两个节名,“NOAM”和“english”是在这两个节中要删选的值
select id, info from books where catsearch(info, '<query> <textquery grammar="context"> NOAM within author and english within language </textquery> </query>', 'order by pubdate')>0;

3.  lexer(索引器)

ctx_ddl.create_preference ('<索引器名>', 'CHINESE_VGRAM_LEXER');

这个一般要和分词器一起使用,要支持中文检索必须使用 CHINESE_VGRAM_LEXER

4. wordlist(分词器)

ctx_ddl.create_preference('<分词器名>', 'BASIC_WORDLIST');
ctx_ddl.set_attribute('<分词器名>','PREFIX_INDEX','TRUE');
ctx_ddl.set_attribute('<分词器名>','PREFIX_MIN_LENGTH',1);
ctx_ddl.set_attribute('<分词器名>','PREFIX_MAX_LENGTH', 5);
ctx_ddl.set_attribute('<分词器名>','SUBSTRING_INDEX', 'YES');

要支持1个字以上的中文分词,就需要用到自定义的分词器

例子:
--中文分词索引
CALL ctx_ddl.create_preference ('CHINESE_LEXER', 'CHINESE_VGRAM_LEXER');
--分词器配置
CALL ctx_ddl.create_preference('ChineseWordList', 'BASIC_WORDLIST');
CALL ctx_ddl.set_attribute('ChineseWordList','PREFIX_INDEX','TRUE');
CALL ctx_ddl.set_attribute('ChineseWordList','PREFIX_MIN_LENGTH',1);
CALL ctx_ddl.set_attribute('ChineseWordList','PREFIX_MAX_LENGTH', 5);
CALL ctx_ddl.set_attribute('ChineseWordList','SUBSTRING_INDEX', 'YES');
--创建索引
Create INDEX idx_book_titile_cn on book_catalog(title)
indextype is ctxsys.CTXCAT parameters('lexer chinese_lexer wordlist chinesewordlist');
--查询:title中有一个列值=三国演义
select id, title 
from book_catalog 
where catsearch(title,'三国','') > 0;

范例:这是一个演示如何创建和使用一个简单的CTXCAT索引的例子

假定你已经拥有了一个数据表 book_catalog

sqlplus>create table book_catalog (
          id        numeric,
          title     varchar2(80),
          publisher varchar2(25),
          price     numeric )

有如下演示数据

1; A History of Goats; SPINDRIFT BOOKS; 50 
2; Robust Recipes Inspired by Eating Too Much; SPINDRIFT BOOKS; 28 
3; Atlas of Greenland History; SPINDRIFT BOOKS; 35 
4; Bed and Breakfast Guide to Greenland; SPINDRIFT BOOKS; 37 
5; Quitting Your Job and Running Away; SPINDRIFT BOOKS; 25

首先我们来创建一个索引集,在进行以下操作前确保当前用户已被正确授权

#把下列包的EXECUTE权限授给当前操作用户

grant execute on CTX_DDL to core;
grant execute on CTX_OUTPUT to core;
grant execute on CTX_DOC to core;

sqlplus>begin
          ctx_ddl.create_index_set('bookset');
          ctx_ddl.add_index('bookset','price');
          ctx_ddl.add_index('bookset','publisher');
        end;

 接着创建一个CTXCAT索引

sqlplus>create index book_idx on book_catalog (title) 
        indextype is ctxsys.ctxcat
        parameters('index set bookset');

运行查询

 SELECT * FROM book_catalog;

--文本查询1
select id, title 
from book_catalog 
where catsearch(title,'Breakfast','price > 10 order by price') > 0;

--文本查询2

select id, title 
from book_catalog 
where catsearch(title,'Breakfast','publisher=''SPINDRIFT BOOKS'' and price > 10 order by price') > 0;

负面影响

【1】无法进行平滑的数据库版本升级

Oracle文本应用程序难以升级到新的数据库版本,Oracle手册提供了两个解决办法:

1. 利用备份数据库进行滚动升级,减少主机停机时间

每一个数据库上执行下列升级参考步骤:

1)CTX_DDL,CTX_OUTPUT,CTX_DOC复制到备份库上并进行数据库升级,但是要注意,以上功能包并不能全部完成复制,存在某些限制,具体可阅读官方文档;

2)在升级数据库上用SYS, SYSTEM, 或 CTXSYS登录;

3)执行脚本:$ORACLE_HOME/ctx/admin/ctx_oh_files.sql

4)查看上述脚本执行后列出的文件清单,把这些文件手工复制到新的oracle home文件夹内 

数据迁移

本章节将结合几个实际操作案例,讲解说明不同环境之间的数据迁移。

主要用到的工具是oracle提供的数据泵工具:exp/imp;expdp/impdp,有关这两个工具的详细介绍可参考本文档【基础知识】之【数据泵】小节

11gR2数据迁移到19c(字符集不同)

环境介绍:源(Ubuntu16+Oracle11.2.0.4(ZHS16GBK))

                  目标(Ubuntu20+Oracle19.3.0.0(AL32UTF8))

方案一:exp/imp(修改客户端字符集)

由于字符集不同,直接使用数据泵做导入导出会导致中文变乱码,采用客户端exp/imp工具,这个工具是根据客户端字符集转换导出的数据文件,而不用关心数据库本身的字符集。

这个工具使用时要注意版本的问题,遵循以下原则:

exp需使用源库版本和目标库版本之间的较低者,即数据迁移是从低版本迁到高版本,则exp用源库的版本;数据迁移是从高版本迁到低版本,则exp用目标库的版本。

imp不受限制,使用目标库版本的就可以了。

如果导出用的版本不一致,还有个补救的办法,找到一个免费工具AlxcTools可以修改dump文件的版本号,注意里面的版本号格式是两位数的,比如数据库版本是11.2.0.4应该写成11.20.40

修改之后就能导入了(还没验证过)。

操作回放(这里采用的是目标库版本exp导出,所以下面都是在目标库上操作):

(目标库)先检查当前客户端字符集(Ubuntu20)

locale #查看当前字符集设置
locale -a #查看支持的字符集,要支持中文选C.UTF-8(也可能是ZH_cn.UTF-8)
#临时修改字符集
export LANG=C.utf8

 (目标库)配置源库和目标库的tns(tnsnames.ora)

#源库tns
GB185=
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 1.*.*.*)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SID = EE)
    )
  )
#目标库tns
TEST_PDB=
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = TEST_PDB)
    )
  )

(目标库)导出源库数据

exp system/****@GB185 file=/opt/oracle/oradata/pdump/exp185.dmp owner=CORE log=/opt/oracle/oradata/pdump/exp185.log
cd /opt/oracle/oradata/pdump
gzip exp185.dmp

#(宿主上执行)容器传输到宿主(非容器环境这步可以跳过)目录必须都存在且有权限
docker cp -L f*********41:/opt/oracle/oradata/pdump/exp185.dmp.gz /oracle/oradata/download/

 (工具)导出到本地,使用AlxcTools修改版本号,再传回服务器

(目标库)导入刚才修改好的dump文件

--修改版本号后上传到服务器,然后传输到容器内部(非容器环境可跳过这一步)
docker cp -L /oracle/oradata/download/exp185.dmp  f*********41:/opt/oracle/oradata/pdump
docker exec -it oracle-19c bash
#创建用户表空间
SQL>CREATE TABLESPACE USERS DATAFILE '/opt/oracle/oradata/GANT/GBOMTEST_PDB/USERS01.dbf' SIZE 50M  AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;
#创建用户
create user core identified by app default tablespace users quota unlimited on users;
#导入dump文件
imp system/******@TEST_PDB file=/opt/oracle/oradata/pdump/exp185.dmp fromuser=CORE ignore=y log=/opt/oracle/oradata/pdump/implog.log
--------------------------------------------------------------
Export file created by EXPORT:V11.20.40 via conventional path
import done in US7ASCII character set and AL16UTF16 NCHAR character set
import server uses AL32UTF8 character set (possible charset conversion)
IMP-00403: 

Warning: This import generated a separate SQL file "/opt/oracle/oradata/pdump/implog_sys.sql" which contains DDL that failed due to a privilege issue.

. importing SYSTEM's objects into SYSTEM
. importing CORE's objects into CORE
。。。。。。

最后都不要忘记检查一下失效包

方案二:expdp/impdp(过渡库)

由于第一种方案存在导入导出工具对数据库版本的依赖,有时会报错,还不好解决,expdp/impdp作为备选方案,万不得已的时候也可以拿来用。

大致思路是这样的:

【1】建一个过渡库,字符集和源库一致,数据库版本和目标库一致;

【2】把源库通过expdp/impdp的方式迁移到过渡库;

【3】用方案一把过渡库迁移到目标库

方案三:expdp/impdp(强改源库字符集)

这是一种简单粗暴的方式,由于Oracle本身并没有提供内建字符集的切换功能,数据库的字符集在数据库创建以后想要修改,只能使用强制切换的方式进行。作为ORACLE非公开的功能,显而易见的是这种操作可能带来严重后果。所以在生产环境绝对不要尝试,此处只作为一种介绍。

步骤如下:

【1】关闭数据库,强制修改源库字符集,使之和目标库一致,重启数据库。

【2】使用expdp/impdp方式数据库迁移

注意:不是所有的字符集转换都能成功,一旦失败,想再改回来就不容易了,可能造成数据永久丢失。

方案四:expdp/impdp+NETWORK_LINK方式

通过DBLINK的方式直接进行全程数据库的迁移,这种方式最大的优点就是操作简单,缺点是需要源库的访问权限,异地迁移时还对网络传输带宽有一定要求,否则大型数据库将很耗时。

操作回放:

(创建目标库)

sql> ALTER SESSION SET container=cdb$root;
sql> create pluggable database DEMO_PDB admin user pdbadmin identified by app roles=(DBA)
file_name_convert=('/opt/oracle/oradata/GANT/pdbseed','/opt/oracle/oradata/GANT/DEMO_PDB');
sql> alter pluggable database DEMO_PDB open;
sql> alter pluggable database DEMO_PDB save state;
sql> ALTER SESSION SET container=DEMO_PDB;
--用户表空间(按照实际情况先建好所有源库上存在的用户表空间)
sql> CREATE TABLESPACE USERS DATAFILE '/opt/oracle/oradata/GANT/DEMO_PDB/USERS01.dbf' SIZE 50M  AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;

(目标库)创建dblink

CREATE PUBLIC DATABASE LINK srcDB11g
CONNECT TO system IDENTIFIED BY "******" USING '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 1.*.*.*)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = EE)))';

 (目标库)tns:12c以上可以使用

tns--12c以上需要配置
destDB19c=
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.*.5.*)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = DEMO_PDB)
    )
  )

(目标库)导入

[oracle@57260bc5ac53 ~]$ impdp \'system/*****@tns\' network_link=srcDB11g schemas=CORE logfile=imp.log EXCLUDE=STATISTICS;
#11g在收集统计信息时可能出现错误,要避免这种错误,建议使用EXCLUDE=STATISTICS屏蔽自动收集表的统计信息,待导完手工收集
#system/*****@tns也可以写成直连的方式@ip:port/<service name>
#如果schema已存在,建议删除之后再导:drop user core cascade;

 问题手记

 【1】导入过程中出现ORA-00910报错:

ORA-39083: Object type TABLE:"MSTDATA"."REPLACE_LONG_MANYSTRING" failed to create with error:
ORA-00910: specified length too long for its datatype

引起这个问题的原因最有可能的两大原因

1)源库字符集和目标库的字符集不一致,解决方案可以参考方案一;

这里要注意一下,Oracle的字符集有两种,一种就是我们常说的数据库字符集即NLS_CHARACTERSET,还有另一个是国家字符集,是用来处理NCHAR和NVARCHAR2以及LOB的,UTF-8使用1-3个字节表示一个字符,而AL16UTF16则统一使用2个字节表示一个字符,按照oracle官方定义varchar2和nvarchar2最大支持4000个字节,所以在utf-8环境下nvarchar2(4000)是可以的,但是当存进去中文时是占3个字节,也就是换算成中文字符的话只能放4000/3个,而在AL16UTF16环境中确定存放2000个中文字符,而存放数字或英文字母时utf-8下明显具有优势,它可以存放4000个,而AL16UTF16却依然只能存放2000个。

2)源库字符集和目标库的字符集一致,则有可能是目标服务器操作系统和数据库客户端以及数据库这三者的字符集存在不一致。

#数据库字符集
SQL>select USERENV('LANGUAGE') from dual;
#操作系统字符集(Linux)
echo $NLS_LANG
#操作系统字符集(Windows)
查看环境变量,没有可以手动增加环境变量NLS_LANG,LANG
#windows客户端字符集
找到ORACLE 目录下的 KEY_OraDb11g_home1,选中KEY_OraDb11g_home1,在右边栏中双击NLS_LANG
在这里可以修改想要的字符集
将上述字符集修改一致即可,不推荐强制修改数据库字符集

【2】导入过程中出现ORA-39126: Worker unexpected fatal error in KUPW$WORKER.PUT_DDLS [TABLE_STATISTICS]  

这是由于在收集统计信息时出现异常,要避免该错误可以在expdp/impdp时指定EXCLUDE=STATISTICS,系统就不收集信息,可以等导完以后手工操作。

管理工具

数据库高可用调优

多路策略需要多个不同存储位置支持,可以是同一设备的不同位置,也可以是不同设备,而后者更符合最佳实践的要求

增加控制文件

查看当前控制文件配置

SQL> select * from v$controlfile;
STATUS	NAME			       IS_ BLOCK_SIZE FILE_SIZE_BLKS	 CON_ID
------- ------------------------------ --- ---------- -------------- ----------
	/opt/oracle/oradata/GANT/contr NO	16384		1142	      0
	ol01.ctl

 修改配置,新目录和文件必须存在,这里不会自动创建,可以现创建也可以在修改后创建

alter system set control_files='/opt/oracle/oradata/GANT/control01.ctl','/opt/oracle/archdata/GANT/control02.ctl' scope=spfile;
shutdown immediate;

创建新目录并复制控制文件到新目录

mkdir /opt/oracle/archdata
mkdir /opt/oracle/archdata/GANT
cp /opt/oracle/oradata/GANT/control01.ctl /opt/oracle/archdata/GANT/control02.ctl

重启数据库

startup

 检查更新

SQL> select name from v$controlfile;

NAME
--------------------------------------------------------------------------------
/opt/oracle/oradata/GANT/control01.ctl
/opt/oracle/archdata/GANT/control02.ctl

增加重做日志文件

查看当前配置

SQL> select GROUP#,MEMBER from v$logfile;

    GROUP# MEMBER
---------- --------------------------------------------------
	 3 /opt/oracle/oradata/GANT/redo03.log
	 2 /opt/oracle/oradata/GANT/redo02.log
	 1 /opt/oracle/oradata/GANT/redo01.log
SQL> alter database add logfile member '/opt/oracle/archdata/GANT/redo01.rdb' to group 1;

Database altered.

SQL> alter database add logfile member '/opt/oracle/archdata/GANT/redo02.rdb' to group 2;
Database altered.


SQL> alter database add logfile member '/opt/oracle/archdata/GANT/redo03.rdb' to group 3;

Database altered.

切换日志检查效果

SQL> alter system switch logfile;

System altered.

SQL> /

System altered.

SQL> /
/
/
System altered.

SQL> 
System altered.

SQL> /

调整归档模式

SQL> archive log list  ##查看当前归档模式
SQL> shutdown immediate
SQL> startup mount;
SQL> alter database archivelog;
SQL> alter database open;

调整闪回模式

SQL> select flashback_on from v$database;

SQL> show parameter db_recovery_file_dest

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest		     string
db_recovery_file_dest_size	     big integer 0

##db_recovery_file_dest_size必须设置,否则无法设置闪回区参数
##db_recovery_file_dest为空没有设置闪回区,需先设置闪回区

SQL> alter system set db_recovery_file_dest_size=2G;

System altered.
SQL> !mkdir /home/oracle/db_recover_file  ##这里可自定义闪回区位置
SQL> alter system set db_recovery_file_dest='/home/oracle/db_recover_file';--这里可以自定义路径

##必须先检查上面闪回区的相关参数是否设置,再开启闪回区
SQL> alter database flashback on;

调整闪回保留策略

SQL> show parameter flashback

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target	     integer	 1440

默认1天,可根据现有资源和业务需求酌情调整, 受db_recovery_file_dest_size参数的影响,如果资源不足,则闪回保留策略将无法达到预期效果

##改为2天,这里仅作演示
SQL> alter system set db_flashback_retention_target=2880;

System altered.

调整控制文件备份策略

设置为自动备份控制文件

RMAN>CONFIGURE CONTROLFILE AUTOBACKUP ON; # default

调整备份文件保留策略

最佳实践:配合备份策略保留7天,超过7天的作为冷备转移到低速存储,本地保留7天备份,可以实现快速恢复到7天内任意一点的数据库

RMAN> show all;
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

另一种是

CONFIGURE RETENTION POLICY TO REDUNDANCY 5;

即保留不超过5份备份。

日常自动化备份脚本

为了保证数据库数据安全,DBA必须在建库初期制定备份策略,并在日常运行过程中部署,自动化实施备份策略。以下是一种典型的备份策略,即以一个星期为周期,周日进行全量备份,周一至周六进行增量备份。基于此备份策略的基本脚本如下:

备份环境准备

这一步主要是创建备份目录+0级备份脚本文件+1级备份脚本文件

export ORACLE_SID=GANT
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=$ORACLE_BASE/product/19c/dbhome_1

export BACKUP_HOME=/opt/oracle/oradata
export BACKUP_DIR=$BACKUP_HOME/archdata/$ORACLE_SID/rman_backups

export SCRIPTS_HOME=$BACKUP_HOME/myscripts
export FULL_0_SCRIPTS=$SCRIPTS_HOME/backup_0_full.sh
export INCR_1_SCRIPTS=$SCRIPTS_HOME/backup_1_incr.sh
export FULL_BACKUP_LOG=$SCRIPTS_HOME/backup_0_full.log
export INCR_BACKUP_LOG=$SCRIPTS_HOME/backup_1_incr.log

mkdir $BACKUP_HOME
mkdir $SCRIPTS_HOME
mkdir $BACKUP_HOME/archdata
mkdir $BACKUP_HOME/archdata/$ORACLE_SID
mkdir $BACKUP_DIR

#+++++++++++ 0 full backup scripts start++++++++++++++++++++
echo '#!/bin/bash' > $FULL_0_SCRIPTS
echo '#script.:backup_0_full.sh' >> $FULL_0_SCRIPTS
echo '#creater:*****' >> $FULL_0_SCRIPTS
echo '#date:2020-01-01' >> $FULL_0_SCRIPTS
echo '#desc:backup full database datafile in archive with rman' >> $FULL_0_SCRIPTS
echo '#connect database' >> $FULL_0_SCRIPTS
echo 'export ORACLE_HOME='$ORACLE_HOME >> $FULL_0_SCRIPTS
echo 'export BACKUP_DIR='$BACKUP_DIR >> $FULL_0_SCRIPTS
echo 'export ORACLE_SID='$ORACLE_SID >> $FULL_0_SCRIPTS
echo 'export BACKUP_LOG='$FULL_BACKUP_LOG >> $FULL_0_SCRIPTS

echo 'echo  rman backup 0 level[start] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG' >> $FULL_0_SCRIPTS

echo '$ORACLE_HOME/bin/rman target / log=$BACKUP_LOG<<EOF' >> $FULL_0_SCRIPTS
echo 'run{' >> $FULL_0_SCRIPTS
echo 'allocate channel c1 type disk;' >> $FULL_0_SCRIPTS
echo 'sql '"'"'alter system switch logfile'"'"';' >> $FULL_0_SCRIPTS
echo 'backup incremental level 0 tag '"'"'$ORACLE_SID_0'"'"' format  '"'"'$BACKUP_DIR/$ORACLE_SID_0_%d_%T_%s'"'"' database include current controlfile;' >> $FULL_0_SCRIPTS
echo 'sql '"'"'alter system archive log current'"'"';' >> $FULL_0_SCRIPTS
echo 'backup filesperset 5 format '"'"'$BACKUP_DIR/$ORACLE_SID_cf0_%d_%T_%s'"'"' archivelog all delete input;' >> $FULL_0_SCRIPTS
echo 'sql '"'"'alter system switch logfile'"'"';' >> $FULL_0_SCRIPTS
echo 'delete noprompt obsolete;' >> $FULL_0_SCRIPTS
echo 'release channel c1;' >>$FULL_0_SCRIPTS
echo '}' >> $FULL_0_SCRIPTS
echo 'EOF' >> $FULL_0_SCRIPTS
echo 'echo rman backup 0 level[end] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG' >> $FULL_0_SCRIPTS
echo '# end' >> $FULL_0_SCRIPTS
#+++++++++++ 0 full backup scripts end++++++++++++++++++++


#+++++++++++ 1 incr backup scripts start++++++++++++++++++++
echo '#!/bin/bash'>$INCR_1_SCRIPTS
echo '#script.:backup_1_incr.sh'>>$INCR_1_SCRIPTS
echo '#creater:***'>>$INCR_1_SCRIPTS
echo '#date:2020-01-01'>>$INCR_1_SCRIPTS
echo '#desc:backup full database datafile in archive with rman'>>$INCR_1_SCRIPTS
echo '#connect database'>>$INCR_1_SCRIPTS

echo 'export ORACLE_HOME='$ORACLE_HOME>>$INCR_1_SCRIPTS
echo 'export BACKUP_DIR='$BACKUP_DIR>>$INCR_1_SCRIPTS
echo 'export ORACLE_SID='$ORACLE_SID>>$INCR_1_SCRIPTS
echo 'export BACKUP_LOG='$INCR_BACKUP_LOG>>$INCR_1_SCRIPTS
echo 'echo  rman backup 0 level[start] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG'>>$INCR_1_SCRIPTS
echo '$ORACLE_HOME/bin/rman target/ log=$BACKUP_LOG<<EOF'>>$INCR_1_SCRIPTS
echo 'run{'>>$INCR_1_SCRIPTS
echo 'allocate channel c1 type disk;'>>$INCR_1_SCRIPTS
echo 'sql '"'"'alter system switch logfile'"'"';'>>$INCR_1_SCRIPTS
echo 'backup incremental level 1 tag '"'"'$ORACLE_SID_1'"'"' format  '"'"'$BACKUP_DIR/$ORACLE_SID_1_%d_%T_%s'"'"' database include current controlfile;'>>$INCR_1_SCRIPTS
echo 'sql '"'"'alter system archive log current'"'"';'>>$INCR_1_SCRIPTS
echo 'backup filesperset 5 format '"'"'$BACKUP_DIR/$ORACLE_SID_cf1_%d_%T_%s'"'"' archivelog all delete input;'>>$INCR_1_SCRIPTS
echo 'delete noprompt obsolete;'>>$INCR_1_SCRIPTS
echo 'release channel c1;'>>$INCR_1_SCRIPTS
echo '}'>>$INCR_1_SCRIPTS
echo 'EOF'>>$INCR_1_SCRIPTS
echo 'echo rman backup 0 level[end] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG'>>$INCR_1_SCRIPTS
echo '#end'>>$INCR_1_SCRIPTS
#+++++++++++ 1 incr backup scripts end++++++++++++++++++++
echo '+++++++Add next text to crontab using <crontab -e>+++++++++'
echo '0 1 * * 0 . '$FULL_0_SCRIPTS' >>'$FULL_BACKUP_LOG' 2>&1'
echo '0 1 * * 1-6 . '$INCR_1_SCRIPTS' >>'$INCR_BACKUP_LOG'  2>&1'

以下是生成后的备份脚本

0级备份脚本

代码如下(红色部分为自定义的备份文件放置的目录):

#!/bin/bash
#script.:backup_0_full.sh
#creater:*****
#date:2020-01-01
#desc:backup full database datafile in archive with rman
#connect database
export ORACLE_HOME=/opt/oracle/product/19c/dbhome_1
export BACKUP_DIR=/home/oracle/oradata2/archdata/GANT/rman_backups
export ORACLE_SID=GANT
export BACKUP_LOG=$BACKUP_DIR/full_backup.log

echo  rman backup 0 level[start] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG

$ORACLE_HOME/bin/rman target / log=$BACKUP_LOG<<EOF
run{
allocate channel c1 type disk;
sql 'alter system switch logfile';
backup incremental level 0 tag '$ORACLE_SID_0' format '$BACKUP_DIR/$ORACLE_SID_0_%d_%T_%s' database include current controlfile;
sql 'alter system archive log current';
backup filesperset 5 format '$BACKUP_DIR/$ORACLE_SID_cf0_%d_%T_%s' archivelog all delete input;
sql 'alter system switch logfile';
delete noprompt obsolete;
release channel c1;
}
EOF
echo rman backup 0 level[end] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG
# end

1级备份脚本

代码如下:

#!/bin/bash
#script.:backup_1_incr.sh
#creater:***
#date:2020-01-01
#desc:backup full database datafile in archive with rman
#connect database

export ORACLE_HOME=/opt/oracle/product/19c/dbhome_1
export BACKUP_DIR=/home/oracle/oradata2/archdata/GANT/rman_backups
export ORACLE_SID=GANT
export BACKUP_LOG=$BACKUP_DIR/incr_backup.log
echo  rman backup 0 level[start] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG
$ORACLE_HOME/bin/rman target/ log=$BACKUP_LOG<<EOF
run{
allocate channel c1 type disk;
sql 'alter system switch logfile';
backup incremental level 1 tag '$ORACLE_SID_1' format '$BACKUP_DIR/$ORACLE_SID_1_%d_%T_%s' database include current controlfile;
sql 'alter system archive log current';
backup filesperset 5 format '$BACKUP_DIR/$ORACLE_SID_cf1_%d_%T_%s' archivelog all delete input;
delete noprompt obsolete;
release channel c1;
}
EOF
echo rman backup 0 level[end] $(date "+%Y%m%d %H%M%S") >> $BACKUP_LOG
#end

crontab设置自动执行备份

接下来使用linux的crontab设置自动执行备份的作业

输入下面的命令,回车

crontab -e

编辑如下内容,保存退出

0 1 * * 0 . /home/oracle/oradata2/myscripts/backup_0_full.sh >>/home/oracle/oradata2/myscripts/backup_0_full.log 2>&1
0 1 * * 1-6 /home/oracle/oradata2/myscripts/backup_1_incr.sh >>/home/oracle/oradata2/myscripts/backup_1_incr.log 2>&1

关于时间的定制规则如下:

说明:
    Linux
    *    *    *    *    *
    -    -    -    -    -
    |    |    |    |    |
    |    |    |    |    +----- day of week (0 - 7) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
    |    |    |    +---------- month (1 - 12) OR jan,feb,mar,apr ...
    |    |    +--------------- day of month (1 - 31)
    |    +-------------------- hour (0 - 23)
    +------------------------- minute (0 - 59)

例子:
    # 每月的最后1天
    0 0 L * * *

要查看crontab内容:

crontab -l

参考文献:linux下的rman自动备份脚本,linux自动运行rman增量备份脚本_jaaaans的博客-CSDN博客

扩充varchar2和nvarchar2支持的最大字节

 这两个类型是通过MAX_STRING_SIZE参数来控制最大字节数的

它有两个选项:STANDARD和EXTENDED

STANDARD是默认选项,支持最大4000字节;

EXTENDED需要通过数据库升级获得支持最大32767字节。

SQL> create table t_demo1 (a nvarchar2(4000));
create table t_demo1 (a nvarchar2(4000))
                                       *
ERROR at line 1:
ORA-00910: specified length too long for its datatype

可以通过alter system命令修改为EXTENDED

升级步骤:

1)  首先把MAX_STRING_SIZE参数修改为EXTENDED;

2)再关闭数据库并以upgrade模式打开数据库

3)通过catcon.pl 脚本来运行 rdbms/admin/utl32k.sql

4)最后正常方式重启数据库

升级案例:环境19c多租户环境

##第一步
SQL>ALTER SESSION SET CONTAINER=CDB$ROOT;
SQL>ALTER SYSTEM SET max_string_size=extended SCOPE=SPFILE;
SQL>shutdown immediate;
SQL>startup upgrade;
SQL>exit;
##第二步
$ cd $ORACLE_HOME/rdbms/admin
$ mkdir $ORACLE_BASE/utl32k_cdb_pdbs_output
$ $ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u SYS --force_pdb_mode 'UPGRADE' -d $ORACLE_HOME/rdbms/admin -l $ORACLE_BASE/utl32k_cdb_pdbs_output -b utl32k_cdb_pdbs_output utl32k.sql
catcon: ALL catcon-related output will be written to [/scratch/mydir/utl32k_cdb_pdbs_output/utl32k_cdb_pdbs_output_catcon_23172.lst]
catcon: See [/scratch/mydir/utl32k_cdb_pdbs_output/utl32k_cdb_pdbs_output*.log] files for output generated by scripts
catcon: See [/scratch/mydir/utl32k_cdb_pdbs_output/utl32k_cdb_pdbs_output_*.lst] files for spool files, if any
Enter Password: #####输入管理员口令
catcon.pl: completed successfully
##第三步
sqlplus / as sysdba
SQL>ALTER SESSION SET CONTAINER=CDB$ROOT;
SQL>shutdown immediate;
SQL>startup;
##第四步
$ cd $ORACLE_HOME/rdbms/admin
$ mkdir $ORACLE_BASE/utlrp_cdb_pdbs_output
$ $ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u SYS --force_pdb_mode 'READ WRITE' -d $ORACLE_HOME/rdbms/admin -l $ORACLE_BASE/utlrp_cdb_pdbs_output -b utlrp_cdb_pdbs_output utlrp.sql
catcon: ALL catcon-related output will be written to [/scratch/mydir/utlrp_cdb_pdbs_output/utlrp_cdb_pdbs_output_catcon_24271.lst]
catcon: See [/scratch/mydir/utlrp_cdb_pdbs_output/utlrp_cdb_pdbs_output*.log] files for output generated by scripts
catcon: See [/scratch/mydir/utlrp_cdb_pdbs_output/utlrp_cdb_pdbs_output_*.lst] files for spool files, if any
Enter Password: #####输入管理员口令
catcon.pl: completed successfully
$

验证效果

SQL> alter session set container=DEMO_PDB;

Session altered.

SQL> create table t_demo1 (a nvarchar2(4000));

Table created.

SQL> create table t_demo1 (a nvarchar2(20000));
create table t_demo1 (a nvarchar2(20000))
                                        *
ERROR at line 1:
ORA-00910: specified length too long for its datatype


SQL> create table t_demo1 (a nvarchar2(16000));

Table created.
#可见,支持最大长度可以达到32K字节,由于nvarchar2是2个字节表示一个字符,所以可容纳的最大字符是16K

故障解决案例

【1】数据库崩溃无法重启-闪回空间不足

SQL> startup
ORACLE instance started.

Total System Global Area 1610609928 bytes
Fixed Size            9135368 bytes
Variable Size         1090519040 bytes
Database Buffers      503316480 bytes
Redo Buffers            7639040 bytes
Database mounted.
ORA-03113: end-of-file on communication channel
Process ID: 278843
Session ID: 379 Serial number: 35806

解决步骤:

1. startup mount 方式启动数据库,监控告警日志

##直接startup也可以看到报错日志,但是这里为了方便查看参数信息,所以用mount方式
SQL> startup mount   
ORACLE instance started.

Total System Global Area 1610609928 bytes
Fixed Size		    9135368 bytes
Variable Size		 1090519040 bytes
Database Buffers	  503316480 bytes
Redo Buffers		    7639040 bytes
Database mounted.
SQL> show parameter recovery

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest		     string	 /home/oracle/db_recover_file
db_recovery_file_dest_size	     big integer 20G
recovery_parallelism		     integer	 0
remote_recovery_file_dest	     string

在另一个窗口打开日志

tail -f /opt/oracle/diag/rdbms/gant/GANT/trace/alert_GANT.log  ##GANT替换成对应的数据库SID

日志中有下面的报错信息

ORA-19804: cannot reclaim 188542464 bytes disk space from 2147483648 bytes limit

问题定位是闪回归档空间耗尽,处理方法有如下几种

1) 物理存储空间足够的情况下,直接调整db_recovery_file_dest_size参数,分配更多的空间

2)物理存储空间不足(db_recovery_file_dest对应的存储容量),整理出可用磁盘空间或增加存储

SQL> show parameter recovery

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest		     string	 /home/oracle/db_recover_file
db_recovery_file_dest_size	     big integer 30G
recovery_parallelism		     integer	 0
remote_recovery_file_dest	     string

检查存储空间

[oracle@57260bc5ac53 ~]$ df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         228G   74G  143G  34% /
tmpfs            64M     0   64M   0% /dev
tmpfs           7.7G     0  7.7G   0% /sys/fs/cgroup
/dev/sda5       228G   74G  143G  34% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs           7.7G     0  7.7G   0% /proc/asound
tmpfs           7.7G     0  7.7G   0% /proc/acpi
tmpfs           7.7G     0  7.7G   0% /proc/scsi
tmpfs           7.7G     0  7.7G   0% /sys/firmware

物理存储还比较充裕,就采用第一种方法

2. 闪回空间分配扩容

SQL> alter system set db_recovery_file_dest_size=30G;  

System altered.

SQL> shutdown immediate
Database closed.
Database dismounted.

SQL> startup
ORACLE instance started.

Total System Global Area 1610609928 bytes
Fixed Size		    9135368 bytes
Variable Size		 1090519040 bytes
Database Buffers	  503316480 bytes
Redo Buffers		    7639040 bytes
Database mounted.
Database opened.

3. [可选] 归档空间清理,虽然有很多物理存储空间,但是归档文件也要定期清理,该转储的转储,腾出足够的归档空间,避免下次再崩溃

rman target /
##用于核对磁盘和磁带上的备份文件,以确保RMAN资料库与备份文件保持同步。注意:该命令只会检查RMAN资料##库所记载的备份文件。当执行crosscheck命令时,如果资料库记录不匹配于备份文件的物理状态,那么该命令##会更新资料库记录的状态信息。备份文件的状态包括:AVALIABLE、UNAVALIABLE、EXPIRED。
RMAN> crosscheck backupset ;
##删除过期备份集和文件
RMAN> delete obsolete;
RMAN> report obsolete;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值