甲骨文_AlphaEdition

来源:互联网 发布:数据运营专员好做吗 编辑:程序博客网 时间:2024/04/29 23:33
一、 安装Oracle
官方文档:Installing and Upgrading – Database Installation Guide
1. GUI建库
 create group and user
Add group: dba,oinstall,oper
Add user: oracle
Change passw: passwd oracle
Create dir: /u01/app/oracle/, change owner, access right 755

 copy DB files.
chown -R <DB files>
chmod -R <DB files>

[oracle@RedQueen ~]$ cd /u01/app/oracle/
unzip p13390677_112040_Linux-x86-64_1of7.zip
cd database/
ll -> oracle:oinstall

 check shm space
df -h /dev/shm/
if tmpfs_Size < 1g
[root@RedQueen Desktop]# mount -t tmpfs shmfs -o size=7g /dev/shm/

 搭建yum仓库
挂载Linux ISO
cd /media/ [Tab] Server/
pwd
" " <- "%20"

cd /etc/yum.repos.d/
[root@RedQueen yum.repos.d]# mv public-yum-ol6.repo public-yum-ol6.repo_bcp
vi server.repo
[server]
name=RedQueen
baseurl=file:///media/OL6.5\%20x86_64\%20Disc\%201\%2020131125/Server
enabled=1
gpgcheck=0

[root@RedQueen yum.repos.d]# yum install binutils* -y
yum install compat-lib* -y
yum install gcc* -y
yum install glibc* -y
yum install ksh* -y
yum install libgcc* -y
yum install libstdc* -y
yum install libaio* -y
yum install make* -y
yum install sysstat* -y

 check配置文件
yum install oracle-rdbms-server-11gR2-preinstall

/etc/sysctl.conf:
cat /etc/sysctl.conf | grep -v ^# | grep ^[^#]
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 4294967295
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576

/sbin/sysctl -p


/etc/security/limits.conf:
cat /etc/security/limits.conf | grep -v ^# | grep ^[^#]
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
oracle soft stack 10240


ifconfig
hostname = /etc/sysconfig/network = /etc/hosts

 环境变量
[root@RedQueen /]# su - oracle
[oracle@RedQueen ~]$ vi .bash_profile
export ORACLE_SID=orcl
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/db_1
export PATH=$PATH:$ORACLE_HOME/bin
export ORACLE_TERM=xterm
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
export CLASSPATH=$ORACLE_HOME/JRE:ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib

[oracle@RedQueen ~]$ source .bash_profile

 run installer
[oracle@RedQueen ~]$ cd /u01/app/oracle/database/
./runInstaller
2. 手工建库
官方文档: Database Administration – Creating and Configuring an Oracle Database – Creating a Database with the CREATE DATABASE Statement.
 确定sid
 创建目录
$ORACLE_BASE: /u01/app/oracle/
$ORACLE_HOME: $ORACLE_BASE/product/11.2.0/db_1/
[Oracle@RedQueen ~] mkdir -p $ORACLE_BASE/admin/<sid>/adump/ -- 审计文件目录
mkdir -p $ORACLE_BASE/admin/<sid>/dpdump/ -- 数据泵目录对象
mkdir -p $ORACLE_BASE/fast_recovery_area/<sid> -- control02.ctl
mkdir -p $ORACLE_BASE/fast_recovery_area/<SID> -- 在线日志
mkdir -p $ORACLE_BASE/oradata/<sid> -- 数据文件、控制文件、日志文件
 设置环境变量实例名
[Oracle@RedQueen ~] echo $ORACLE_SID
export ORACLE_SID = <sid>
echo $ORACLE_SID
 创建参数文件
[Oracle@RedQueen ~] cd $ORACLE_HOME/dbs/init<sid>.ora
cat init.ora | grep -v ^# > init<sid>.ora

db_name=’<SID>’
memory_target=1G
processes=150
audit_file_dest=’<ORACLE_BASE>/admin/<sid>/adump’
audit_trail=’db’
db_block_size=8192
db_domain=’’
db_recovery_file_dest=’<ORACLE_BASE>/fast_recovery_area’
db_recovery_file_dest_size=2G
diagnostic_dest=’<ORACLE_BASE>’
dispatchers=’(PROTOCAL=TCP) (SERVICE=ORCLXDB)’
open_cursors=300
remote_login_passwordfile=’EXCLUSIVE’
undo_tablespace=’UNDOTBS1’
control_files = (‘<ORACLE_BASE>/oradata/<sid>/controlfile01.ctl’,’ <ORACLE_BASE>/fast_recovery_area/<sid>/controlfile02.ctl’)
compatible=’11.2.0’
 创建密码文件
[Oracle@RedQueen ~] cd $ORACLE_HOME/dbs/
orapwd file=orapwd<sid> password=<passw>
ls -l
 连接数据库
[Oracle@RedQueen ~] sqlplus / as sysdba
SYS@<sid>> startup nomount

[ERROR] ORA-00845: MEMORY_TARGET not supported on this system
[Solution]
官方文档:Installing and Upgrading – Database Quick Installation Guide for Linux x86-64 – Oracle Database Preinstallation Requirements. “Ctrl+F: ORA-00845”
[root@RedQueen ~] mount -t tmpfs shmfs -o size=7g /dev/shm
SYS@<sid>> startup nomount
SELECT status FROM v$instance; -- STARTED
 创建动态参数文件
SYS@<sid>> CREATE SPFILE FROM PFILE;
 创建数据库
官方文档: Database Administration –Creating and Configuring an Oracle Database – Creating a Database with the CREATE DATABASE Statement -
SYS@<sid>>
CREATE DATABASE <sid>
USER sys IDENTIFIED BY oracle
USER system IDENTIFIED BY oracle
LOGFILE GROUP 1 (‘/u01/app/oracle/oradata/<sid>/redo01a.log’, ’/u02/logs/my/redo01b.log’) SIZE … BLOCKSIZE … ,
GROUP 2 (‘/u01/app/oracle/oradata/<sid>/redo02a.log’, ’/u02/logs/my/redo01b.log’) SIZE … BLOCKSIZE … ,
GROUP 3 (‘/u01/app/oracle/oradata/<sid>/redo03a.log’, ’/u02/logs/my/redo01b.log’) SIZE … BLOCKSIZE …
MAXLOGFILES 5
MAXLOGMEMBERS 5
MAXLOGHISTORY 100
MAXDATAFILES 10
MAXINSTANCES 2
CHARACTER SET US7ASCII
NATIONAL CHARACTER SET AL16UTF16
EXTENT MANAGEMENT LOCAL
DATAFILE ‘/u01/app/oracle/oradata/<sid>/system01.dbf’ SIZE 325M REUSE
SYSAUX DATAFILE ‘/u01/app/oracle/oradata/<sid>/sysaux01.dbf’ SIZE 325M REUSE
DEFAULT TABLESPACE users
DATAFILE '/u01/app/oracle/oradata/<sid>/users01.dbf'
SIZE 500M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED
DEFAULT TEMPORARY TABLESPACE tempts1
TEMPFILE '/u01/app/oracle/oradata/<sid>/temp01.dbf'
SIZE 20M REUSE
UNDO TABLESPACE undotbs1
DATAFILE '/u01/app/oracle/oradata/<sid>/undotbs01.dbf'
SIZE 200M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
 创建数据字典视图
SYS@Orcl> @?/rdbms/admin/catalog.sql
 PL/SQL package和procedure
SYS@Orcl> @?/rdbms/admin/catproc.sql
[oracle@RedQueen ~] sqlplus system/oracle
SYSTEM@Orcl> @?/sqlplus/admin/pupbld.sql
SELECT status FROM v$instance; -- OPEN

[ERROR] sqlplus / as sysdba
Connected to an idle instance.
[Solution] startup
二、 Linux开机自动启动Oracle和监听
[root@RedQueen ~] vi /etc/oratab
orcl:/u01/app/oracle/product/11.2.0/db_1:Y

vi /etc/rc.d/rc.local
su - oracle -c 'dbstart'
su - oracle -c 'lsnrctl start'
三、 设置SQLPlus提示符
[oracle@RedQueen ~] vi /u01/app/oracle/product/11.2.0/db_1/sqlplus/admin/glogin.sql
set sqlprompt "_user'@'_connect_identifier> "
/** _user: 当前登陆用户名;_connect_identified: 连接串名*/
四、 升级Oracle
1. 查看数据库与OPatch版本号
[oracle@RedQueen ~] cd $ORACLE_HOME/OPatch/
./opatch
./opatch lsinventory

2. 关闭数据库、监听器
SYS@orcl> shutdown immediate
host lsnrctl stop

3. 升级OPatch
cp, unzip.
[oracle@RedQueen ~] cp -r ./OPatch/ $ORACLE_HOME
$ORACLE_HOME/OPatch/opatch lsinventory

4. 升级数据库
cp, unzip.
[oracle@RedQueen ~] cd ./1234567890
$ORACLE_HOME/OPatch/opatch apply
$ORACLE_HOME/OPatch/opatch lsinventory

5. 更新dba_registry_history视图为最新PSU信息
SYS@orcl> startup
host lsnrctl start
alter system register; /**将数据库信息注册到监听器(动态监听器)里*/
@?/rdbms/admin/catbundle.sql psu apply //执行脚本

6. "CheckActiveFilesAndExecutables" failed
UtilSession failed: Prerequisite check "CheckActiveFilesAndExecutables" failed.
a. 关闭数据库与监听器
SYS@orcl> shutdown immediate
host lsnrctl stop
b. 使用fuser命令查看并kill进程
[oracle@RedQueen 1234567890]$ /sbin/fuser <file name>
kill -9 1234 3456 8901 3409
五、 删除Oracle
1. 关闭数据库、监听、进程
SYS@Orcl> shutdown immediate
[root@RedQueen ~] lsnrctl stop
ps -ef | grep ora

2. deinstall
[root@RedQueen ~] cd /u01/app/oracle/product/11.2.0/dbhome_1/deinstall
./deinstall

3. 删除目录
[root@RedQueen ~] rm -f /usr/local/bin/dbhome
rm -f /usr/local/bin/oraenv
rm -f /usr/local/bin/coraenv
[root@RedQueen ~] rm -f /etc/oratab
rm -f /etc/orainst.loc
[root@RedQueen ~] rm -rf /opt/ORCLfmap

4. 删除用户和用户组
userdel -r oracle
groupdel oinstall
groupdel dba
groupdel oper

5. 删除$ORACLE_BASE目录
[root@RedQueen ~] rm /u01/app/oracle/
六、 em (enterprise manager)
SYS@orcl> alter system register;
[oracle@RedQueen ~]$ lsnrctl start
emctl start / stop / status dbconsole
七、 启动与关闭
官方文档
理论:Database Administration – Database Concept – Oracle Database Instance;
命令:Database Administration – Administrator’s Guide – Starting Up and Shutting Down.

数据库状态 文件加载项
SHUTDOWN null
NOMOUNT 参数文件
MOUNT 控制文件
OPEN 数据文件、日志文件

表格 1 - SHUTDOWN命令
数据库行为 ABORT IMMEDIATE TRANSACTIONAL NORMAL
允许新用户连接 No No No No
等待现有Session结束 No No No Yes
等待现有Transaction结束 No No Yes Yes
检查点 No Yes Yes Yes

执行startup force命令,关闭数据库的时候,不会执行CKPT检查点,启动的时候会进行实例恢复instance recover.
八、 Oracle概念
1. 数据库名
A. 查看数据库名
 SELECT name FROM v$database;
 show parameter db
 查看参数文件
B. 查看数据库域名
 SELECT value FROM v$parameter WHERE name = ‘db_domain’;
 show parameter domain
 查看参数文件
C. 全局数据库名称
全局数据库名称 = 数据库名.数据库域名
D. 修改数据库名
-- 建议创建数据库时就要确定好,不要修改。
步骤如下:
 关闭数据库
 修改参数文件中的DB_NAME为新的数据库名
 启动数据库到NOMOUNT状态,创建控制文件
 启动数据库
2. 数据库实例名
-- 参数为instance_name, 用于和操作系统联系的标识。
A. 数据库实例名和ORACLE_SID
两者的值是一致的,但是有区别的。数据库实例名instance_name是Oracle数据库的参数;而ORACLE_SID是操作系统的环境变量。操作系统想要访问数据库实例名,必须通过ORACLE_SID(在WinNT平台,ORACLE_SID还必须要放进注册表当中)。
ORACLE_SID必须与instance_name一致,否则会报错 – Unix: “ORACLE is not available”; WinNT: “TNS: 协议适配器错误”。
B. 查看数据库实例名
 SELECT instance_name FROM v$instance;
 show parameter instance
 查看参数文件
3. 数据库服务名
-- SERVICE_NAME. 如果数据库有域名,则数据库服务名就是全局数据库名;否则就是数据库名。主要是数据库与客户端连接的时候会使用到数据库服务名。
4. 数据库逻辑生存期
数据库逻辑生存期,incarnation。“ALTER DATABASE OPEN RESETLOGS; ”会将重做日志的序列号重置为0(但SCN号不会被重置)。通常是不完全恢复后,原来重置日志里面的内容对恢复后的数据库不再有效,所以需要清零。
一旦产生了新的incarnation,就不能直接恢复到旧的incarnation的数据库状态,必须先切换到旧的incarnation,再恢复(恢复完又会产生一个新的incarnation)。
 切换数据库逻辑生存期
RMAN> shutdown immediate
startup mount
reset database to incarnation n;
九、 SQL
官方文档:Database Administration – SQL and PL/SQL – SQL Language Reference
1. 基本查询语句
SELECT * | { [DISTINCT] column | expression [alias], … }
FROM table
[WHERE condition [ (Subquery /*不需要order by除非执行TOP-N查询*/) ] ]
[ORDER BY column_name /*default ASC*/, alias1 DESC, 3 /*3rd col*/ DESC /*null是最大值*/
/*
A. ORDER BY只能出现一次,而且出现在最后
B. ORDER BY只识别第一个SELECT子句中的名字,不能是第二个等等
*/
];

Expression:
+ - * /
通配符:
% -- 表示0个或多个字符
_ -- 表示1个字符*/
转义:like ‘%table\_name%’ ESCAPE ‘\’
逻辑条件:
AND OR NOT
比较运算符:
BETWEEN… AND…(包含上下限值) LIKE IS NULL
= > >= < <= <> (子查询中的单行比较符,单行单列)
IN(set) ANY ALL (子查询中的多行操作符,多行单列)

查询前n行数据:
SELECT * FROM <tab> WHERE rownum <= n;
A. EXISTS:
IN (单列), EXISTS(结果集);
IN子查询返回结果,EXISTS子查询返回BOOL值
IN首先执行子查询,将结果放在一个索引化了的临时表当中,再执行主查询;EXISTS首先执行主查询,然后运行子查询直到它找到第一个匹配项。所以当子查询的表记录少于主查询的表记录时,用IN的效率高;反之亦然,主查询表 < 子查询表,EXISTS。

P.S.
A. 列别名包含空格、特殊字符、区分大小写必须用双引号引起来
B. ‘||’ 可以连接列、字符串
C. 临时替代变量&,调用替代变量&&,DEFINE定义变量
D. 字符、日期必须使用单引号
E. 单引号转义:a. ‘‘ b. q[‘]
F. 规则优先:
a. + - * /
b. ||
c. = > >= < <=
d. IS [NOT] NULL LIKE [NOT] IN
e. [NOT] BETWEEN
f. <> ^= !=
g. NOT
h. AND
i. OR
B. With子句
返回查询块的结果集是放在临时表空间存储起来的,所以能提高查询性能。
WITH alias1 [(col1, col2 …)] AS (<query>) [, alias2 [(col1, col2 …)] AS (<query>)]
SELECT … FROM alias …;
C. 层次查询
SELECT [LEVEL], column, exp …
FROM table
[WHERE condition(s)]
[START WITH start_condition(s)]
[CONNECT BY PRIOR prior_condition(s)];
-- LEVEL: 伪列,用于表示树的层次。例如SELECT count(distinct LEVEL) “Level” FROM …
-- start_condition(s): 控制从哪个节点开始
/* prior_conditions: 定义父节点和子节点的关系。prior 表示前一条记录,即下一条返回记录的manager_id应当等于前一条记录的employee_id, 所以”CONNECT BY PRIOR employee_id = manager_id”(自上而下)不等于”CONNECT BY PRIOR manager_id = employee_id”(自下而上)*/

例1:修剪分支
SELECT * FROM EMP
WHERE last_name != ‘Higgins’ -- 消除这个叶节点的作用
CONNECT BY PRIOR employee_id = manager_id
AND last_name != ‘Higgins’ -- 消除这个分支的作用;

例2:格式化层次查询(使用左填充n * level - 1个空格,美观作用)
SELECT level, lpad(‘ ‘, 2 * level -1) || ename AS “Ename”, job
FROM emp
START WITH ename = ‘KING’
CONNECT BY PRIOR empno = mgr;
2. INSERT语句
INSERT INTO table_name
[(col1 [, col2 …] | [DEFAULT])] -- 每次插入1行数据
| [(Subquery)] -- 不用VALUES关键字
VALUES (val1 [, val2 …]);

P.S.
A. 字符、日期必须使用单引号
B. 可以用替代变量的方式插入值
3. 多表INSERT
INSERT /*condition: */ [ALL | FIRST]
[WHEN condition THEN] INTO target_table1 VALUES (…, …)
[ELSE] INTO target_table2 VALUES (…, …)
SELECT … FROM source_table WHERE …;

旋转INSERT
INSERT ALL
INTO target_table VALUES (colA, colB, col1)
INTO target_table VALUES (colA, colB, col2)
INTO target_table VALUES (colA, colB, col3)
INTO target_table VALUES (colA, colB, col4)
SELECT colA, colB, col1, col2, col3, col4 FROM source_table;
4. UPDATE语句
UPDATE table_name
SET col1 = val1 [, DEFAULT] [, col2 = (Subquery /*单行单列*/) …]
[WHERE condition];
5. DELETE语句
DELETE [FROM] table_name
[WHERE condition | Subquery]; /*高水位线不变*/
6. TRUNCATE语句
TRUNCATE TABLE table_name;
/*
A. 高水位线清0;
B. Date Definition Language语句,不易恢复,要用闪回数据库
*/
7. CREATE TABLE语句
CREATE TABLE [schema.]table_name ( col datatype [DEFAULT exp /*指定缺省值*/] [, …] )
[AS Subquery];
8. ALTER TABLE语句
ALTER TABLE table_name
ADD | MODIFY (col1 datatype [DEFAULT exp] [, col2 datatype] …)
| DROP (col)
| READ ONLY
| SET UNUSED COLUMN column_name
| DROP UNUSED COLUMNS
| RENAME COLUMN old_name TO new_name;
9. MERGE TABLE语句
MERGE INTO table_name alias
USING (table | view | sub_query) alias
ON (join_condition)
WHEN MATCHED THEN
UPDATE SET
col1 = val1,
col2 = val2
WHEN NOT MATCHED THEN
INSERT (column_list)
VALUES (values);
10. 分区表
官方文档:Data Warehousing and Business Intelligence – VLDB and Partitioning Guide [- Partition Administration – Viewing Information About Partitioned Tables and Indexes].
当表的大小达到GB级别,或者需要将历史数据与当前数据分开的时候,就需要用到分区表。分区表可以提高性能、可用性、节约维护成本、均衡I/O.
 查看分区表信息:
官方文档:Database Administration – Reference.
SELECT table_name, partitioning_type, partition_count, status, def_tablespace_name
FROM dba_part_tables;
SELECT table_name, partition_name, tablespace_name FROM dba_tab_[sub]partitions;
SELECT name, column_name FROM dba_[sub]part_key_columns;
SELECT * FROM dba_[sub]part_col_statistics;
SELECT * FROM dba_part_indexes;
SELECT * FROM dba_ind_[sub]partitions;
 查询、更新、删除分区表
SELECT * FROM | UPDATE | DELETE FROM<tab> PARTITION (<p01>);
 移动分区到新的表空间
ALTER TABLE <tab> MOVE PARTITION <p2> TABLESPACE <tbs2>;
 删除、Truncate分区
ALTER TABLE <tab> DROP | TRUNCATE PARTITION <p2>;
 拆分分区
ALTER TABLE
SPLIT PARTITION <p_n> AT (n-x) INTO (PARTITION p_n-x TABLESPACE <tbs1>, PARTITION p_n+y TABLESPACE <tbs2>);
 合并分区
ALTER TABLE <tab> MERGE PARTITIONS <p1>, <p2> INTO <p1>;
 交换分区
ALTER TABLE <tab> EXCHANGE PARTITION <p2> WITH TABLE <tab2>;
 重命名分区
ALTER TABLE <tab> RENAME PARTITION <p3> TO <p2>;
A. 范围分区
CREATE TABLE (

) PARTITION BY RANGE (<id>) (
PARTITION <p1> VALUES LESS THAN (n) [TABLESPACE <tbs1>],
PARTITION <p2> VALUES LESS THAN (<maxvalue>) [TABLESPACE <tbs2>]
)
增加分区:
SYS@Orcl> ALTER TABLE <tab>
ADD PARTITION <p3> VALUES THAN (m) [TABLESPACE <tbs2>];
ORA-14074: partition bound must collate higher than that of the last partition.
/* maxvalue边界分区。需要先备份边界分区的数据,删除,添加新的分区,再添加边界分区,导入数据。*/
ALTER TABLE <tab> DROP PARTITION <p_max>;
ALTER TABLE <tab>
ADD PARTITION <p3> VALUES THAN (m) [TABLESPACE <tbs2>];
ALTER TABLE <tab>
ADD PARTITION <p_max> VALUES THAN (<maxvalue>) [TABLESPACE <tbs3>];
B. 列表分区
CREATE TABLE <tab> (

) PARTITION BY LIST (<col>) (
PARTITION <p1> VALUES (‘<a1>’[, ‘<a2>’ | NULL | DEFAULT]) [TABLESPACE <tbs1>] [STORAGE (INITIAL nM)],
PARTITION <p2> VALUES (‘<b2>’[, ‘<b2>’ | NULL | DEFAULT]) [TABLESPACE <tbs2>]
)
增加DEFAULT分区:
ALTER TABLE <tab> ADD PARTITION <pn> VALUES (DEFAULT)
[STORAGE (INITIAL Nm NEXT nM) TABLESPACE <tbs3> NOLOGGING];
C. Hash分区
均匀分布。
CREATE TABLE <tab> (

) PARTITION BY HASH (<id>) (
PARTITION <p1> TABLESPACE <tbs1>,
PARTITION <p2> TABLESPACE <tbs2>
)
增加分区:
ALTER TABLE <tab>
ADD PARTITION <p3> TABLESPACE <tbs3>;
D. Interval分区
范围分区的一种扩展。如果插入的数据值与当前的分区都不匹配,Interval分区可以字段创建分区。
CREATE TABLE <tab> (

) PARTITION BY RANGE (<id>) INTERVAL (n | numtoyminterval(1, ‘year’) | numtodsinterval(7, ’day’) | numtodsinterval(1, ‘month’) ) ( -- 新创建分区步长为n | 1年的时间 | 1个月的时间
PARTITION <p1> VALUES LESS THAN (n) [TABLESPACE <tbs1>],
PARTITION <p2> VALUES LESS THAN (<maxvalue>) [TABLESPACE <tbs2>]
)
查看分区表情况:
SELECT partition_name, high_value FROM user_tab_partitions WHERE table_name = ‘’;
不能增加分区,只能转换为范围分区 / Interval分区
ALTER TABLE <tab>
SET INTERVAL () | SET INTERVAL (numtoyminterval(1, ‘MONTH’));

E. 外键分区
CREATE TABLE <tab1> (
…,
CONSTRAINT <pk_tab1_col1> PRIMARY KEY (<col1>)
) PARTITION BY RANGE (<col1>) (
PARTITION <p1> VALUES LESS THAN (n),
PARTITION <p2> VALUES LESS THAN (<maxvalue>)
)

CREATE TABLE <tab2> (
…,
CONSTRAINT <fk_tab1col1_tab2col2> FOREIGN KEY (<col2>) REFERENCES tab1<col1>
) PARTITION BY REFERENCE (fk_tab1col1_tab2col2);
F. 虚拟列分区
SYS@Orcl> CREATE TABLE <tab> (
a int, b int, c int as (a + b)
) PARTITION BY RANGE (c) (
PARTITION <p1> VALUES LESS THAN (n),
PARTITION <p2> VALUES LESS THAN (maxvalue)
);

INSERT INTO <tab> VALUES (1, 2, 3);
ORA-54013: INSERT operation disallowed on virtual columns.
INSERT INTO <tab> VALUES (1, 2);
G. 复合分区
主分区:范围、列表、Interval分区;子分区:范围、列表、Hash分区
 范围 – Hash分区
CREATE TABLE <tab> (

) PARTITION BY RANGE (<col1>) SUBPARTITION BY HASH (col2)
SUBPARTITIONS 2^n STORE IN (<tbs1, tbs2 … >) (
PARTITION <p1> VALUES LESS THAN …
PARTITION <p2> VALUES LESS THAN …
STORE IN (<tbs3, tbs4 … >),
PARTITION <p3> VALUES LESS THAN (maxvalue) (
SUBPARTITION <p3_s1> TABLESPACE <tbs4>,
SUBPARTITION <p3_s2> TABLESPACE <tbs5>
)
);
增加分区:
ALTER TABLE <tab>
ADD PARTITION <p3> VALUES LESS THAN … COMPRESS
SUBPARTITION 2^n STORE IN <tabs3>;
 范围 – 列表分区
查看子分区表数据:
SELECT * FROM <tab> SUBPARTITION(<p1_s1>);
CREATE TABLE <tab> (

) TABLESPACE <tbs1>
PARTITION BY RANGE (<col1>)
SUBPARTITION BY LIST (<col2>) (
PARTTITION <p1> VALUES LESS THAN … (
SUBPARTITION <p1_s1> VALUES (<’A’, ‘B’>),
SUBPARTITION <p1_s2> VALUES (<’C’, ‘D’>)
), PARTITION <p2> VALUES LESS THAN (maxvalue) (
SUBPARTITION <p2_s1> VALUES (<’A’, ‘B’>),
SUBPARTITION <p2_s2> VALUES (<’C’, ‘D’>)
)
)
增加分区:
ALTER TABLE <tab>
MODIFY PARTITION <p1> ADD SUBPARTITION <p1_s3> VALUES (<’E’, ‘F’>) [TABLESPACE <tbs2>];

增加范围分区为子分区:
ALTER TABLE <tab>
MODIFY PARTITION <p1> ADD SUBPARTITION <p1_s3> VALUES LESS THAN (<maxvalue>);
增加索引分区:
ALTER INDEX <i1>
REBUILD PARTITION <p1> TABLESPACE <tbs1>;
H. 分区索引
官方文档:Data Warehousing and Business Intelligence – VLDB and Partitioning Guide – Partition Administration – Maintaining Partitions.
分为本地分区索引、全局分区索引。当对分区表进行维护性操作的时候,全局分区索引会失效。维护性操作包括:Adding Partitions, Dropping Partitions, Exchanging Partitions, Merging Partitions, Modifying a Subpartition Template, Moving Partitions, Rebuiding Index Partitions, Renaming Partitions, Splitting Partitions, Truncating Partitions… 不同分区上的维护性操作也有不同。
CREATE INDEX <i01> on <tab>(col) LOCAL | GLOBAL;
/*前缀分区索引:索引的字段是分区键;
非前缀分区索引:索引的字段不是分区键。*/
11. 临时表
CREATE GLOBAL TEMPORARY TABLE table_name (
column_name data_type, …
)
ON COMMIT DELETE /*事务级别*/| PRESERVE ROWS /*会话级别*/;
12. 外部表
A. Oracle_Loader & Oracle_Datapump
Oracle提供两种驱动程序去访问外部表:oracle_loader(默认), oracle_datapump(先将另外一个数据库中的数据导出成一个文件,然后再访问外部文件).
外部表占用的是操作系统的空间,而非数据库的空间。
建立目录对象
CREATE OR REPLACE DIRECTORY dir_name AS ‘‘;
授权读写
GRANT READ [, WRITE] ON DIRECTORY dir_name TO user01;
创建外部表
官方文档: Information Intergration – Utilities – External Tables.
 oracle_loader
CREATE TABLE “<tab>” (

)
ORGANIZATION external (
TYPE oracle_loader
DEFAULT DIRECTORY <dir>
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE CHARACTERSET <US7ASCII>
BADFILE <dir>:’<rjt.bad>’
LOGFILE ‘<ext.log>’
READSIZE 1024 -- 缓冲区大小,单位MB.
SKIP n -- 跳过的行数,也就是文件前面需要跳过的header
FIELDS TERMINATED BY “,” LDRTRIM
REJECT ROWS WITH ALL NULL FIELDS (
“<col1>” <CHAR(255)> TERMINATED BY “,”,

)
)
LOCATION (
‘<ext.dat>’
)
) REJECT LIMIT UNLIMITED
/
 oracle_datapump
-- 操作系统上看到的是二进制文件;不支持直接将数据插入外部表
CREATE TABLE <tab> (

) ORGANIZATION EXTERNAL (
TYPE oracle_datapump
DEFAULT DIRECTORY <dir>
LOCATION (
‘<tab1.exp>,<tab2.exp>’
)
) PARALLEL n -- 两种表,并行度就为2
AS -- 将查询结果放入外部表 ,oracle_loader不支持SELECT语句。
SELECT …
FROM <emp> JOIN <dept>
ON emp.deptno = dept.deptno
B. SQL*Loader
官方文档: Information Intergration – Utilities – SQL*Loader Concepts.
SQL*Loader是导入外部数据的工具,这些数据会占用数据库的空间。
SQL*Loader的体系结构包括:Input Datafiles、Loader Control File、Log File、Bad Files、Discard Files。SQL*Loader需要一个控制文件来控制数据文件的装载,包括3个组成部分:外部会话相关信息、一个或多个INTO TABLE块、导入的数据源(可选)。
流记录格式(默认):不指定记录长度,通过终结符来判断记录是否结束;指定数据文件为流记录格式:INFILE <file.dat> [“<terminator_string>”]. 例如:INFILE ‘exp.dat’ “str ‘|/n’” -- 使用“|”或者回车作为记录的终止符,X’09’是Tab键。
[oracle@RedQueen ~]$ sqlldr
Usage: SQLLDR keyword=value [,keyword=value2, … ]
direct -- 直接路径导入。将新的数据追加在已有数据的后面,数据直接写入数据文件,跳过buffer cache,原来表中的空闲空间不能使用,引用完整性的约束会被忽略,不会除非insert触发器,并更新该块的高水位线,不需要commit。不支持簇表,插入时其他用户不能实施DML操作。
[oracle@RedQueen ~]$ sqlldr \’\/ as sysdba\’
LOAD DATA
INFILE ‘<exp_1.dat>’ “str ‘|/n’”
INFILE ‘<exp_2.dat>’
INTO TABLE <tab> [PARTITION <part>] [APPEND]
WHEN <a1 = ‘1’> -- 第1列值为1
FIELDS TERMINATED BY ‘,’ optionally enclosed by ‘”’ -- 如果有双引号,则认为是一个整体
(<a1 FILTER POSITION(1), > <col1 CHAR(n)>, <col2 CHAR(n)>) -- 过滤a1字段
INTO TABLE <tab> [PARTITION <part>] [APPEND]
WHEN <a1 = ‘2’> -- 第2列值为2
FIELDS TERMINATED BY ‘,’ optionally enclosed by ‘”’ -- 如果有双引号,则认为是一个整体
(<a1 FILTER POSITION(1), > <col1 CHAR(n)>, <col2 CHAR(n)>) -- 过滤a1字段
13. 视图
DROP | CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW view_name [(alias [, alias] …)]
AS subquery
[WITH CHECK OPTION [CONSTRAINT constraint_name] /*创建视图时有WHERE子句才用, 保证INSERT, UPDATE INTO view_name后, 数据可以被视图查询出来*/]
[WITH READ ONLY [CONSTRAINT constraint_name]];

CREATE OR REPLACE VIEW dept_emp (name, minsal, maxsal, avgsal)
AS
SELECT dept.department_name, MIN(emp.salary), MAX(emp.salary), AVG(emp.salary)
FROM employee emp LEFT JOIN department dept
ON (dept.department_id = emp.department_id)
GROUP BY dept.department_name;
/* ON condition: 生成临时表时的条件,不论ON condition是否为真,都会返回左表记录;
WHERE condition: 临时表生成后,再对临时表过滤的条件,此时已经没有LEFT JOIN含义,WHERE condition为假就过滤掉 */
14. 序列
CREATE | ALTER| DROP SEQUENCE sequence_name
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE n | NOMAXVALUE}]
[{MINVALUE n | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE n – 提高查询效率, 但占内存空间 | NOCACHE}];
首次调用应先使用<sequence_name>.nextval
15. 同义词
DROP | CREATE [PUBLIC] SYNONYM synonym_name FOR object_name;
16. SQL语言的分类
DQL, Data Query Language (select)
DML, Data Manipulation Language (update, insert, delete)
DDL, Data Definition Language (create, alter)
DCL, Data Control Language (grant, revoke)
TCL, Transaction Control Language (commit, rollback, savepoint)
17. set
UNION / UNION ALL, INTERSECT, MINUS
18. 显示表结构
DESC[RIBE] table_name
19. 查看SQL执行计划
A. EXPLAIN PLAN FOR <SQL>;
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY);
B. PL/SQL Developer
-- 不支持set autotrance on
File -> New -> Explain Plan Window. Cardinality: 表示执行行数
C. SQLPlus
a. SYS@orcl> @?sqlplusadminplustrce.sql
GRANT PLUSTRACE TO Scott;
Scott@orcl> set autotrace traceonly
b. Scott@orcl> set autotrance on
20. 时区
A. 查看Linux时区 / 时间
[oracle@RedQueen ~] cat /etc/sysconfig/clock
Scott@orcl> select sysdate from dual;
B. 查看数据库时区
Scott@orcl> SELECT dbtimezone FROM dual;
C. 查看session时区
Scott@orcl> SELECT sessiontimezone FROM dual;
D. 修改时间格式
Scott@orcl> ALTER SESSION SET nls_date_format = ‘YYYY-MON-DD HH24:MI:SS’;
E. 查看当前时间
Scott@orcl> SELECT
sessiontimezone, current_date /*会话时间*/, sysdate /* OS时间*/,
current_timestamp /*系统时间戳*/, localtimestamp /*会话时间戳*/
FROM dual;
F. 查看时区名称
Scott@orcl> SELECT tzname FROM v$timezone_names WHERE tzname like ‘‘;
G. 修改数据库时区
-- 建议安装数据库时选择好
SYS@orcl> ALTER DATABASE SET time_zone = ‘+8:00’;
ORA-30079: cannot alter database timezone when database has TIMESTAMP WITH LOCAL TIME ZONE columns.
SYS@orcl> SELECT u.name||’.’||o.name||’,’||c.name tsltz_column
FROM sys.obj$ o, sys.col$ c, sys.user$ u
WHERE c.type#=231
AND o.obj#=c.obj#
AND u.user#=o.owner#;
TSLTZ_COLUMN
------------------------------
OE.ORDERS.ORDER_DATE
SYS@orcl> ALTER TABLE oe.orders DROP COLUMN order_date;
ALTER DATABASE SET time_zone = ‘+8:00’;
shutdown immediate
startup
SELECT dbtimezone FROM dual;
H. 修改会话时区
Scott@orcl> ALTER SESSION SET TIME_ZONE = ‘+8:00’ | dbtimezone | local /*系统时间*/;
I. INTERVAL
INTERVAL ‘integer [ - integer ]’ {YEAR | MONTH} [ (precision) ] [TO {YEAR | MONTH}]
例:INTERVAL ‘37 - 10’ YEAR(2 /*默认*/) TO MONTH
21. 正则表达式
官方文档:Database Administration – SQL and PL/SQL – SQL Language Reference – D Oracle Regular Expression Support (Multilingual Regular Expression Syntax, 元字符)

正则表达式元字符
[] 表示包含的意思
() 表示里面的是一个字表达式
\s 表示任意空白字符(space)
\w 表示任意字母
\d 表示数字
0-9 表示数字
a-z 表示小写字母
A-Z 表示大写字母
^ 表示以xx开头
$ 表示以xx结尾。例如”xx$”
* 匹配前面的子表达式任意次
? 匹配前面的子表达式零次或一次
+ 匹配前面的子表达式一次或多次
. 除换行符\n和回车符\r之外的任意一个字符
| 表示两项之间的选择。
例如”^([a-z]+|[0-9]+)$”表示小写字母或者数字字符串
\ 转义一个字符。表示后面的字符在原文中是普通字符,一般放在[]里面的尾部
{m,n} 表示出现次数的范围。m<出现次数<n
\5 表示第5个字符组

Oracle字符类
[[:alpha:]] 表示任意字母
[[:digit:]] 表示任意数字
[[:lower:]] 表示任意小写字母
[[:upper:]] 表示任意大写字母
[[:alnum:]] 表示任意字母和数字
[[:space:]] 表示任意空白字符
[[:punct:]] 表示任意标点符号
[[:xdigit:]] 表示任意16进制数字,相当于[0-9a-fA-F]

正则表达式函数
格式:regexp_<普通字符函数>()
A. regexp_like(<expression>, <regexp> [, <match_option>])
match_option:
i 不区分大小写
n 允许使用可以匹配任意字符的操作符
m 将<expression>作为一个包含多行的字符串
例:SELECT * FROM people WHERE regexp_like (name, '^T.*$', 'i');
B. regexp_instr(<expression>, <regexp>
[, start_position [, occurrence [, return_option [, match_option [, sub_expression_n]]]]]
)
-- start_position序号从1开始,而不是0.
-- occurrence是指第几次出现
/* return_option如果为0,则返回这个匹配的字符是在第几位;如果非0,则返回这个匹配字符后一位的位置*/
-- sub_expression_n表示返回第n个子表达式的位置
例1:SELECT regexp_instr ('1234.98', '\.') position FROM dual;
例2:
SELECT regexp_instr
('0123456789', -- expression
'(123)(4(56)(78))', -- regexp
1, -- start
1, -- occurrence
0, -- return_option
'i', -- match_option (ignore case)
3) – indicate which sub-expression to search
"Position"
FROM dual;
/* (123) -- 1 (4(56) -- 3 (78) -- 4 ) --2 */
C. regexp_substr(<expression>, <regexp>
[, start [, occurrence [, match_option]]]
)
例:SELECT id, regexp_substr (html, 'http[a-zA-Z0-9\.:/]*') url FROM html;
D. regexp_replace(<expression>, <regexp>
[, replace_with [, start [, occurrence [, match_option]]]]
)
例:SELECT regexp_replace ('15/12/2014', '^([0-9]{2})/([0-9]{2})/([0-9]{4})$', '\3-\2-\1') new_format FROM dual;
-- '\3-\2-\1'表示将字符组顺序调换为3, 2, 1. 并且分隔符为”-”
E. regexp_count(<expression>, <regexp>
[, start [, occurrence [, match_option]]]
)

例1:column的值包含网址,需要截取出来
SELECT id, regexp_substr (html, ‘http[0-9a-zA-Z\:/.]*’) from html_tab;

例2:添加check约束,检查email地址是否包含”@”
ALTER TABLE client_info ADD CONSTRAINT email_address
CHECK (regexp_like (email, '@')) novalidate;
十、 SQLPlus cmd
官方文档:Database Administration – SQL*Plus User’s Guide and Reference

SYS@orcl> help index / help cmd
start filename = @ filename = @@ filename 执行SQL脚本文件

run / ‘/’ 重复执行上一条命令
accept x prompt ‘asdf’
select * from table_name where condition = &x; 交互式命令

archive log (list) 归档日志
clear buffer / columns / screen 清空
column 格式化列的显示形式
column COLUMN_NAME heading COLUMN_HEADING 改变缺省的列标题
col COLUMN_NAME format a8 改变列的显示长度
col COLUMN_NAME format $9,999.00 / yyyy-mm-dd / hh24:mi:ss 格式化number类型列的显示方式
col COLUMN_NAME null text 用text代替null值
break on COLUMN_NAME_A
compute function_name(sum… ) of COLUMN_NAME_B on COLUMN_NAME_A
select… from… 计算


conn 连接
disc 断开连接
edit 编辑缓冲区内容
execute 执行存储过程
exit 退出
get (filen_name) 将文件的SQL语句导入到buffer当中
ho 在SQLPlus中执行一个操作系统命令
pause [prompt_msg_text] 暂停执行的存储过程
print 打印绑定变量
set auto[commit] on / off 设置当前session是否自动提交
set echo on / off 在用start命令执行一个SQL脚本时,是否显示SQL语句
set feed[back] n / on /off 默认>6才显示结果集的行数,=1则无论查询到多少行都返回
set hea[ding] on / off 是否显示列标题
set lin[esize] n 设置每一行的字符数
set newp[age] n 设置每页之间相隔行数
set pages[ize] n 设置每一页多少行
set timing on / off 显示花费的执行时间
set pause on / off 逐页显示
set time on / off 显示时间
set verify on / off 显示变量替换过程新旧值
show all 显示当前环境变量
show parameter parameter_name 显示参数值
show rel[ease] 显示数据库版本
show SGA 显示SGA大小
show user 显示当前用户名
shutdown 关闭数据库
spool file_name
spool off 将显示内容(命令、结果集)输出到指定文件

startup 开启数据库
! 返回Linux提示符,exit返回SQLPlus提示符

十一、 数据字典和性能视图
1. 数据字典
A. DICTIONARY
DESC[RIBE] DICT[IONARY];
SELECT * FROM DICT WHERE table_name = ‘USER_OBJECTS’;
B. 前缀
USER_ (用户拥有的对象的信息), ALL_ (用户可以访问的对象的信息), DBA_ (数据库中所有对象的信息), V$
C. 查看对象信息
SELECT object_name FROM <prefix>_objects WHERE object_type = ‘TABLE’;
-- 表、列、约束、视图、序列等
D. 查看表信息
a. SELECT * FROM tab;
b. SELECT table_name FROM <prefix>_tables;
E. 查看列信息
SELECT table_name, column_name FROM <prefix>_tab_columns WHERE table_name = ‘‘;
F. 查看约束信息
a. SELECT owner, table_name, constraint_name, constraint_type, status
/* ENABLED, DISABLED */
FROM <prefix>_constraints WHERE table_name = ‘‘;
b. SELECT owner, table_name, column_name constraint_name
FROM <prefix>_cons_columns WHERE table_name = ‘‘; -- 查看约束关联的列的名字
G. 查看视图信息
SELECT * FROM <prefix>_views;
H. 查看索引信息
a. SELECT * FROM <prefix>_indexes;
b. SELECT index_name, column_name FROM <prefix>_ind_columns WHERE table_name = ‘‘;
I. 查看同义词信息
SELECT * FROM <prefix>_synonyms;
J. 查看序列信息
SELECT * FROM <prefix>_sequences;
K. 查看注释
a. SELECT * FROM <prefix>_tab_comments;
b. SELECT * FROM <prefix>_col_comments;
COMMENT ON TABLE | COLUMN name IS ‘‘;
L. 查看控制文件名字、位置和状态
SHOW PARAMETER control_file;
M. 查看参数
SHOW PARAMETER parameter_name
N. 查看区信息
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –
SELECT segment_name, extent_id, block_id, blocks FROM dba_extents [| user_extents];

查看表所在的文件的ID、块的起始ID、大小
SELECT file_id, block_id, bytes FROM dba_extents WHERE segment_name = ‘’;
O. 查看数据文件信息
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –
SELECT * FROM dba_data_files;
P. 查看自由空间信息
SELECT * FROM dba_free_space [| user_free_space];
2. 性能视图
A. 数据文件
VIEW DESC
V$DATAFILE Contains datafile information from the control file
V$DATAFILE_HEADER Contains information from datafile headers

B. 控制文件
VIEW DESC
V$DATABASE Displays database information from the control file
V$CONTROLFILE Lists the names of control files
列出实例中所有控制文件的名字和状态信息
V$CONTROLFILE_RECORD_SESSION Displays information about control file record sessions
列出控制文件中关于记录部分的信息
V$PARAMETER Displays the names of control files as specified in the control_files initialization parameter
列出所有参数的位置和状态信息

C. 参数文件
DESC v$parameter
SELECT name, value, isses_modifiable, issys_modifiable, ismodified FROM v$parameter;
/* issys_modifiable: deferred – ALTER SYSTEM … deferred; 只对新的session生效;
Ismodified: modified – 使用了ALTER SESSION命令进行了修改;system_mod – 使用了ALTER SYSTEM命令进行了修改;false – 没有被修改过*/
D. 重做日志文件
VIEW DESC
V$LOG Display the redo log file information(group#, sequence#, members, status /* CURRENT, INACTIVE, ACTIVE, UNUSED*/ , first_change#, next_change#) from the control file
V$LOGFILE Identifies redo log groups and members and member status(group#, status /* <blank> –可以正常使用; stale – 许久未用(日志太大); invalid – 无效(新增或损坏) */ , type, member, is_recovery_dest_file /*查看是否需要恢复*/ )
V$LOGHISTORY Contains log history information

E. 内存分配状态
官方文档:Database Administration – Administrator's Guide – Managing Memory – Memory Management Reference – Memory Management Data Dictionary Views.

VIEW DESC
V$SGA Displays summary information about the system global area (SGA).
V$SGAINFO Displays size information about the SGA, including the sizes of different SGA components, the granule size, and free memory.
V$SGASTAT Displays detailed information about how memory is allocated within the shared pool, large pool, Java pool, and Streams pool.
V$PGASTAT Displays PGA memory usage statistics as well as statistics about the automatic PGA memory manager when it is enabled (that is, when PGA_AGGREGATE_TARGET is set). Cumulative values in V$PGASTAT are accumulated since instance startup.
V$MEMORY_DYNAMIC_COMPONENTS Displays information on the current size of all automatically tuned and static memory components, with the last operation (for example, grow or shrink) that occurred on each.
V$MEMORY_TARGET_ADVICE Displays information that helps you tune MEMORY_TARGET if you enabled automatic memory management.
V$SGA_TARGET_ADVICE Displays information that helps you tune SGA_TARGET.
V$PGA_TARGET_ADVICE Displays information that helps you tune PGA_AGGREGATE_TARGET.

十二、 函数
1. 字符函数
LOWER, UPPER, INITCAP
CONCAT -- ‘||’, SUBSTR -- 从1开始, LENGTH, INSTR(‘string’, ‘substring’, num), LPAD(‘string’, new_length, ‘fill_string’), RPAD, TRIM(‘char’ from ‘string’), LTRIM(‘string’, ‘char’), RTRIM, REPLACE
2. 数字函数
ROUND, TRUNC
3. 日期函数
MONTHS_BETWEEN, ADD_MONTHS, NEXT_DAY, LAST_DAY -- 月的最后一天
ROUND(sysdate, ‘MON’) – 将DD四舍五入到MON, TRUNC
4. RR纪年
最靠近的YY年
SELECT sysdate FROM dual; -- 获取OS系统时间
5. 显性转换函数
NUMBER <- -> CHAR <- -> DATE
YYYY, YEAR -- 全拼写格式, MM, MONTH, MON, DY -- 星期几三位缩写, DAY -- 星期几全拼, DD, HH24, MI, SS, DD “of” MON, ddspth -- 序数, fm -- 去除前导0和空格
9 0 $ . , L -- 使用本地货币符号
格式模板元素: 官方文档 - Database Administration -> SQL Language Reference -> Basic Elements of Oracle SQL -> Format Models.
6. 空值函数
NVL (exp1, exp2) -- 如果exp1为空则返回exp2,否则返回exp1
NVL2 (exp1, exp2, exp3) -- 如果exp1不为空则返回exp2,为空返回exp3
NULLIF (exp1, exp2) -- 如果相同则返回空值,否则返回exp1
COALESCE (exp1, exp2 … expN) -- 返回第一个不为空的参数
7. 条件表达式
A. CASE语句
CASE [exp] WHEN comparison_exp1 THEN return_exp1
[WHEN comparison_exp2 THEN return_exp2
WHEN comparison_expN THEN return_expN
ELSE else_exp]
END
B. DECODE语句
DECODE ( col | exp, search1, result1,
search2, result2… ]
[, default] )
8. 常用分组函数
AVG ( [ NVL (col, 0) ] ) -- 处理空值, COUNT ( * | [DISTINCT] col), MAX, MIN, STDDEV -- 方差, SUM, VARIANCE
用于SELECT子句
9. 分组数据
[ GROUP BY group_by_exp ]
[HAVING condition [ (Subquery) ] ]
A. 出现在SELECT列表中的非分组列(没有用分组函数处理过的)必须出现在GROUP BY子句当中
SELECT col1, COUNT (col2)
FROM tab1
GROUP BY col1
B. 分组列可以不出现在SELECT列表中
SELECT col1, col2, COUNT (col3)
FROM tab1
GROUP BY col1, col2
C. 不能使用WHERE子句限制分组列,应该使用HAVING子句
D. 分组列:用分组函数处理过的 / GROUP BY子句中的列
10. 高级分组函数
A. ROLLUP
GROUP BY ROLLUP group_by_expression 横向统计、不分组统计
Example: 查询各个部门中各个工种的平均工资、各个部门的平均工资、所有员工的平均工资
SYS@orcl> SELECT deptno, job, avg (sal) FROM emp GROUP BY ROLLUP (deptno, job);
DEPTNO JOB AVG (SAL)
------ ------ ------
10 A 9999.99
10 B 9999.33
10 9999.77
20 A 8888.88
20 B 8888.33
20 8888.77
30 A 7777.77
30 B 7777.33
30 7777.66
40 A 6666.66
40 B 6666.33
40 6666.77
9000
ROLLUP: 查询各个col1中各个col2的F (*)、各个col1的F (*)、所有F (*)

B. CUBE
GROUP BY CUBE group_by_expression 横向统计、纵向统计、不分组统计
Example: 查询各个部门中各个工种的平均工资、各个部门的平均工资、各个工种的平均工资、所有员工的平均工资
SYS@orcl> SELECT deptno, job, avg (sal) FROM emp GROUP BY CUBE (deptno, job);
DEPTNO JOB AVG (SAL)
------ ------ ------
9000
A 1111.44
B 7777.00
10 9999.77
10 A 9999.99
10 B 9999.33
20 8888.77
20 A 8888.88
20 B 8888.33
30 7777.66
30 A 7777.77
30 B 7777.33
40 6666.77
40 A 6666.66
40 B 6666.33
CUBE: 查询各个col1中各个col2的F (*)、各个col1的F (*)、各个col2的F (*)、所有F (*)
C. GROUPING
SELECT [ colN, ] group_function (col) … , GROUPING (exp)
/* 辨别记录是否由小计组成,区别是记录中存储的null还是ROLLUP或者CUBE产生的null,返回0, 1. */
D. GROUPING SETS
GROUP BY GROUPING SETS () 合并分组查询
/* 效果相当于UNION ALL,但效率更高,只需一次分组,语句简单,成员越多性能提升越明显 */
Example: 查询各个部门的平均工资、各个工种的平均工资
SYS@orcl> SELECT deptno, job, avg (sal) FROM emp GROUP BY GROUPING SETS (deptno, job);
DEPTNO JOB AVG (SAL)
------ ------ ------
10 9999.99
20 8888.88
30 7777.77
40 6666.66
A 1111.11
B 2222.22
GROUPING SETS: 查询各个col1的F (*)、各个col2的F (*)
A. 列匹配
十三、 体系结构
官方文档:Database Administration – Database Concepts – Oracle Database Instance, Memory Architecture, Process Architecture.

1. 数据库
-- 至少一个
定义:一组用于存储数据的文件(数据文件、控制文件、日志文件/*默认至少有两个联机重做日志文件*/)(归档重做日志文件、参数文件、警告文件/* WARNINGS, ERRORS */、跟踪文件/*存放后台进程和服务器进程的跟踪信息*/、口令文件/*保存特权用户的口令*/、闪回日志文件、备份文件等等,这些不是数据库文件,只是数据库的辅助文件而已)。
A. 物理结构
a. 参数文件
官方文档:Database Administration – Reference.
路径:$ORACLE_HOME/dbs/
spfile服务器端参数文件 pfile静态参数文件
文件名 spfile<SID>.ora init<SID>.ora
二进制文件 文本文件
P.S. 建议使用,Oracle会优先查找。
简化参数管理;又可以使用Rman备份。 SYS@Orcl> CREATE pfile [ = ‘/home/oracle/init<SID>.ora’ ] FROM spfile /*已设定的参数*/ [ | memory /*所有参数*/ ];

查看数据库是使用spfile还是pfile?
SYS@Orcl> show parameter spfile; -- 看VALUE值是否为空。

动态参数:在数据库运行时可以修改的参数;
------
静态参数:只能修改参数文件来改变的初始化参数。
SELECT name FROM v$parameter WHERE isses_modifiable = ‘FALSE’ and issys_modifiable = ‘FALSE’;
 修改参数文件方式:可以用spfile创建pfile,修改pfile,再创建spfile:
SYS@Orcl> CREATE pfile FROM spfile;
SHUTDOWN IMMEDIATE;
oracle@RedQueen ~>$ vi init<SID>.ora
SYS@Orcl> STARTUP pfile = ‘init<SID>.ora’;
CREATE spfile FROM pfile;
STARTUP FORCE;
SHOW PARAMETER spfile;

ALTER SYSTEM … scope = spfile [| both /*默认*/] [| memory];
b. 控制文件
官方文档:Database Administration – Administrator’s Guide – Managing Control Files.
spfile -> control_files参数
SHOW PARAMETER control;

二进制文件,记录的数据库的物理结构。查看控制文件内容:”strings $ORACLE_BASE/oradata/<sid>/control01.ctl | more”。每个数据库至少有一个控制文件,但通常都会进行多路复用(要求同时可用)。
控制文件是用来查找数据库的文件的。控制文件主要有以下信息:
数据库名称和数据库唯一标识符(DBID),SELECT name, dbid FROM v$database;
创建数据库的时间戳(SCN号)
表空间信息DATAFILE
联机重做日志文件LOGFILE(切换时的日志序列号之类的日志历史信息等)、有关数据文件、归档重做日志文件的信息(物理结构信息,例如文件名称、位置)
Rman备份(Rman写入位置、状态之类的元数据信息等)
检查点信息
字符集信息

循环重用部分:
control_file_record_keep_time参数,超过这个参数值(单位:天)的可变部分参数就会被覆盖。
非循环重用部分:
例如文件位置、大小,日志位置,数据库名等,以及以下参数:
MAXDATAFILES, MAXLOGFILES, MAXLOGMEMBERS, MAXLOGHISTORY, MAXINSTANCES …
控制文件会为每个数据文件预留180个字节的空间,用于记载数据文件名称、大小、状态,以及检查点信息等。

P.S. 控制文件会跟踪数据库的结构变化,并更新SCN号。例如至少每隔3秒,检查点进程CKPT会在控制文件中,记录有关联机重做日志中检查点的SCN号。

 增加(减少)控制文件
查看原有控制文件位置
SELECT name FROM v$controlfile;
增加控制文件
ALTER SYSTEM set control_files = ‘<path>/a.ctl’, ‘<path>/b.ctl’, ‘<path>/new.ctl’ scope = spfile;
关闭数据库
SYS@Orcl> SHUTDOWN IMMEDIATE
复制控制文件
cp <path>/old.ctl <path>/new.ctl
重新启动数据库
SYS@Orcl> STARTUP
查看控制文件信息
SELECT name FROM v$controlfile;
 备份控制文件
官方文档:Database Administration – Administrator’s Guide – Managing Control Files – Backing up Control Files.
ALTER DATABASE backup controlfile to ‘/home/oracle/bcp.ctl’;
/*二进制文件。
cp cmd */
ALTER DATABASE backup controlfile to trace [as ‘/home/oracle/bcp.ctl’];
/*文本文件。
查看默认路径:
SYS@Orcl> SELECT value FROM v$diag_info WHERE name = ‘Default Trace File’;
-- $ORACLE_BASE/admin/<sid>/udump/ */
 使用备份的控制文件开启数据库(控制文件的恢复)
SYS@Orcl> RECOVER DATABASE using backup controlfile;
ALTER DATABASE open resetlogs;
ALTER TABLESPACE temp add tempfile ‘<path>/temp.dbf’ [size n reuse autoextend on next m maxsize l];
 重建控制文件
*创建脚本
cat old.ctl | grep -v ^- >new.sql
启动数据库到nomount状态
SYS@Orcl> STARTUP nomount
@./new.sql
启动到open状态
SYS@Orcl> ALTER DATABASE open

ORA-01113: file n needs media recovery
恢复数据库(刷新控制文件SCN号)
SYS@Orcl> RECOVER DATABASE
打开数据库
ALTER DATABASE open;
查看控制文件
SELECT name FROM v$controlfile;
------ Or
CREATE CONTROLFILE SET DATABASE prod
LOGFILE GROUP 1 (‘<path1/redo1_1.log>’, ‘<path2/redo1_2.log>’),
GROUP 2 (‘<path1/redo2_1.log>’, ‘<path2/redo2_2.log>’),
GROUP 3 (‘<path1/redo3_1.log>’, ‘<path2/redo3_2.log>’)
RESETLOGS
DATAFILE ‘<path>/system01.dbf’ SIZE nM,
‘<path>/rbs01.dbs’ SIZE nM,
‘<path>/users01.dbs’ SIZE nM,
‘<path>/temp01.dbs’ SIZE nM,
MAXLOGFILES n
MAXLOGMEMBERS n
MAXLOGHISTORY n
MAXDATAFILES n
MAXINSTANCES n
ARCHIVELOG;
c. 重做日志文件
官方文件:Database Administration – Administrator’s Guide – Managing the Redo Log
DML操作的实际过程:

注释:
i. 申请undo数据块,修改回滚段段头(undo) -> 产生redo
修改回滚段(undo)的数据块 -> 产生redo(log buffer, 最后会被记录在日志文件当中)
ii. 申请数据块存放新的数据,对原始数据块进行修改 -> 产生redo
iii. Rollback -> undo block -> block -> 产生redo
对回滚段段头信息的相关撤销 -> 产生redo -> 事务结束

由于是先在重做日志缓冲区记录重做项信息,然后在数据库高速缓冲区修改数据,所以当介质故障(数据文件)、实例失败的时候,可以用重做日志文件来恢复。
Oracle要求至少需要2个重做日志组(建议要有3个,也建议他们存储在不同的磁盘当中,均衡I/O,降低一起丢失的风险),“SELECT group# FROM v$log; ”;每个日志组至少要有1个日志成员(建议要有2个,这两个日志成员是互为镜像备份的,也即具有相同的日志序列号、大小等,建议他们存储在不同的磁盘当中,均衡I/O,降低一起丢失的风险;日志序列号是日志文件的唯一标识,当前日志序列号存储在控制文件和所有数据文件的头部),“SELECT member FROM v$logfile; ”。
添加重做日志文件:
SYS@Orcl> ALTER DATABASE add logfile ‘<path>/<name>.log’ size nM;
手动切换重做日志文件:
SYS@Orcl> ALTER SYSTEM switch logfile;
 强制检查点
主要目的是为了进行快速的实例恢复。“FAST_START_MTTR_TARGET”是一个用于加快实例恢复的参数(单位:秒),需要设置一个合理的值,如果太大,实例恢复时间会很长;如果太小,增加系统I/O负担(DBWn)。实际上是内存中的dirty buffer所需的恢复时间(estimated_mttr)到达FAST_START_MTTR_TARGET所设定的时间,那么检查点就会被触发。
查看预计的恢复时间:
SELECT recovery_estimated_ios, actual_redo_blks, target_redo_blks, target_mttr, estimated_mttr FROM v$ instance_recovery;
查看建议的恢复时间:
SELECT mttr_target_for_estimate, dirty_limit, estd_cache_writes, estd_cache_write_factor, estd_total_writes, estd_total_write_factor FROM v$mttr_target_advice;
 重做日志组的个数
查看警告文件($ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace/alert_<sid>.log)和跟踪文件($ORACLE_BASE/diag/rdbms/<sid>/<sid>/),如果出现“Checkpoint not complete”或者“Redo Log Group not archived”,那么就需要添加日志组了。
增加日志组
ALTER DATABASE add logfile [group n] (‘<path>/<redo>.log’ [, ‘<path2>/<redo02>.log’]) [size nM];
增加日志成员
ALTER DATABASE add logfile member ‘<path>/<redo>.log’ [REUSE] to group n;
删除日志组
SELECT group#, status FROM v$log;
ALTER SYSTEM switch logfile;
ALTER SYSTEM checkpoint;
SELECT group#, status FROM v$log;
ALTER DATABASE drop logfile group n;
删除日志成员
SELECT group#, status FROM v$log;
ALTER SYSTEM switch logfile;
ALTER SYSTEM checkpoint;
SELECT group#, status FROM v$log;
ALTER DATABASE drop logfile member ‘<path>/<redo>.log’;
ho rm <path>/<redo>.log
查询重做日志组的基本信息
SELECT group#, sequence#, bytes, members, status FROM v$log;
改变日志文件位置或名称:
SELECT group#, status FROM v$log;
ALTER SYSTEM switch logfile;
ALTER SYSTEM checkpoint;
SELECT group#, status FROM v$log;
SELECT group#, member FROM v$logfile;
ho mv <old_path>/<old_redo>.log <new_path>/<new_redo>.log
ALTER DATABASE rename file ‘<old_path>/<old_redo>.log’ to ‘<new_path>/<new_redo>.log’;
SELECT name FROM v$datafile;
 清空日志文件
-- 日志文件损坏的时候可以尝试(日志组丢失其中一个日志成员)
[Oracle@RedQueen ~]$ less /$ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace/alert_<sid>.log
/ORA-00312

SYS@Orcl> SELECT group#, status FROM v$log;
[ --丢失当前组所有日志成员
SHUTDOWN IMMEDIATE
STARTUP MOUNT]
ALTER DATABASE clear [unarchived /*不进行归档*/ ] logfile group n;
 清空日志组
-- 建议开启归档模式
ALTER DATABASE MOUNT;
[ -- 丢失当前的日志组
ALTER DATABASE clear unarchived logfile group n;
ALTER SYSTEM set “_allow_resetlogs_corruption”=true scope=spfile;
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
RECOVER DATABASE until cancel; -- 丢失联机重做日志、归档日志。
cancel
ALTER DATABASE OPEN resetlogs;
SELECT group#, member FROM v$logfile;
ALTER DATABASE clear unarchived logfile group n;
ALTER SYSTEM reset “_allow_resetlogs_corruption” scope=spfile;
]
/*丢失非当前的日志组*/
SELECT group#,sequence#,archived,status FROM v$log;
ALTER DATABASE clear logfile group n;
ALTER DATABASE OPEN;
 重做日志文件的大小
太小,日志切换频繁,检查点次数增加,系统性能降低(CKPT -> DBWN -> I/O);太大,一来日志文件很大,归档时间很长,导致复用重做日志文件的时候,LGWR需要等待,二来实例恢复时间也会很长。建议根据生产环境情况,将日志切换时间调整到15~30分钟。
 重做项信息
更改的SCN和时间戳
更改事务的事务ID
事务提交时的SCN和时间戳
所做更改的操作类型
被修改的数据段的名称和类型
d. 归档文件
官方文档:Database Administration – Administrator’s Guide – Managing Archived Redo Logs [– Running a Database in ARCHIVELOG Mode]
LGWR -> Online Redo Log Files -> ARCn -> Archived Redo Log Files
保障可以实现对介质的恢复(实例恢复由重做日志缓冲区、重做日志文件来完成),但不是数据库文件的一部分。
 改变日志操作模式(归档、非归档模式)
SYS@Orcl> archive log list [|SELECT name, log_mode FROM v$database;]
SHUTDOWN IMMEDIATE
STARTUP MOUNT
ALTER DATABASE archivelog [| noarchivelog];
ALTER DATABASE OPEN;
archive log list [|SELECT name, log_mode FROM v$database;]
[Oracle@RedQueen ~]$ ps -ef | grep ora_ | grep arc
 显示归档日志位置
- 归档日志默认放在闪回恢复区
SYS@Orcl> SELECT destination FROM v$archive_dest; [| archive log list]
show parameter DB_RECOVERY_FILE_DEST
[Oracle@RedQueen ~]$ cd $ORACLE_BASE/fast_recovery_area/<SID>/archivelog/<os_date>/
 改变归档日志位置到本机其它地方或者远程主机
官方文档:Database Administration – Administrator’s Guide – Managing Archived Redo Logs – Setting Initialization Parameters for Archive Destinations
以下方法1和方法2互斥

方法1:
SYS@Orcl> show parameter log_archive_dest_
[Oracle@RedQueen ~]$ mkdir <path1>
mkdir <path2>
SYS@Orcl> ALTER SYSTEM set log_archive_dest_1 = ‘location=<path>’;
ORA-16019: cannot use LOG_ARCHIVE_DEST_1 with LOG_ARCHIVE_DEST or
LOG_ARCHIVE_DUPLEX_DEST

ALTER SYSTEM set LOG_ARCHIVE_DUPLEX_DEST = ‘’;
ALTER SYSTEM set LOG_ARCHIVE_DEST = ‘’;

ALTER SYSTEM set log_archive_dest_1 = ‘location=<path>’;
ALTER SYSTEM set log_archive_dest_2 = ‘service=<DG_standby>’;
-- 1 ~ 10: local or remote; 11 ~ 31: remote only
show parameter log_archive_dest_
ALTER SYSTEM archive log current;

/*停用启用某个Log Archive Destination:
show parameter log_archive_dest_
ALTER SYSTEM set log_archive_dest_state_n = defer [| enable];
show parameter log_archive_dest_
*/

方法2:
[Oracle@RedQueen ~]$ mkdir <path1>
mkdir <path2>
SYS@Orcl> ALTER SYSTEM set LOG_ARCHIVE_DEST = ‘<path1>’;
ORA-16018: cannot use LOG_ARCHIVE_DEST with LOG_ARCHIVE_DEST_n or
DB_RECOVERY_FILE_DEST

show parameter DB_RECOVERY_FILE_DEST
/*如果使用方法2,就不能设置闪回恢复区。而且local only。
关闭闪回恢复区: */
ALTER SYSTEM set db_recovery_file_dest = ‘’;
ALTER SYSTEM reset db_recovery_file_dest_size;
/*关闭时,先把db_recovery_file_dest set为null,
后reset db_recovery_file_dest_size;开启时则反过来。*/
STARTUP FORCE
show parameter DB_RECOVERY_FILE_DEST

ALTER SYSTEM set log_archive_dest = ‘<path1>’;
ALTER SYSTEM set log_archive_duplex_dest = ‘<path2>’;
ALTER SYSTEM archive log current;
 控制本地归档成功的最小个数
show parameter log_archive_min_succeed_dest
ALTER SYSTEM set log_archive_min_succeed_dest = 2;
 查看归档日志信息
SELECT name, sequence#, first_change#, next_change# FROM v$archived_log;
 查看归档日志内容(二进制文件)
[oraclee@RedQueen ~]$ cd $ORACLE_BASE/fast_recovery_area/<SID>/archivelog/<os_date>
strings <archivelog>.arc | grep <info>
 手工归档
ALTER SYSTEM switch logfile [| ALTER SYSTEM archive log current];
 查看日志历史信息
SELECT * FROM v$loghist;
 配置归档进程
SELECT * FROM v$archive_processes; [| show parameter log_archive_max_processes]
ALTER SYSTEM set log_archive_max_processes = n; --建议至少保留2个
e. 密码文件
路径:$ORACLE_HOME/dbs/orapw<sid>
存放的是特权用户(SYS, SYSTEM)的口令信息,普通用户的口令是存放在数据字典当中的(所以数据库必须要处于open状态,才能使用普通用户连接到数据库)。

认证方式参数:
· remote_login_passwordfile = none | exclusive /*默认*/ | shared
/*位于参数文件$ORACLE_HOME/dbs/spfile$ORACLE_SID.ora当中。
修改的时候需要加上scope = spfile. 并重启生效。*/
· SQLNET.AUTHENTICATION_SERVICES = none | all | nts (windows)
/*位于$ORACLE_HOME/network/admin/sqlnet.ora当中(需要自己创建)。*/
none: 关闭操作系统验证(使用密码验证)
all: 本机密码文件认证、操作系统验证,远程不可以使用密码文件认证
nts: 用于Windows平台
REMOTE_LOGIN_PASSWORDFILE SQLNET.AUTHENTICATION_SERVICES 操作系统验证 远程登录
exclusive /*默认*/ 没有
$ORACLE_HOME/network/admin/sqlnet.ora Y Y
exclusive none N Y
exclusive all Y Y
none 没有
$ORACLE_HOME/network/admin/sqlnet.ora Y N
none none N N
none all Y N
注释:
能够使用“sqlplus / as sysdba” 进行登录,也就是开启了操作系统验证,而并没有使用用户名和口令,也就没有使用密码文件orapw<sid>;
能够使用“sqlplus system/oracle@orcl”,也就是进行了远程登录。

密码文件的建立:
orapwd file=orapworcl password=oracle force=y
-- file=orapworcl要注意密码文件名格式,force=y是指允许覆盖
B. 逻辑结构
官方文档:Database Administration – Database Concepts – Logical Storage Structure.

存储数据的最小单位是数据块,分配空间的最小单位是区。段分为很多种,比如临时段Temp、回滚段undo、数据段、索引段、分区段等等,它是为用户对象(例如表、索引等)分配的一组区域。
查看表空间与数据文件对应关系:SELECT tablespace_name, file_name FROM dba_data_files;
查看段的信息:SELECT tablespace_name, segment_name, segment_type FROM user_segments;
-- 创建表时,会分配一个名称和表名相同的表段
a. 数据块
数据块内部结构:

Common and Variable Header
Table Directory
Row Directory
事务巢ITL Slot
Free Space
Row Data
-- 随着行数据Row Data的增加,数据块头部也会不断增大。
-- Common and Variable Header包括有:数据块地址、段的类型等,以及对于事务管理块,Oracle数据块在其块头保留有活动的和历史的事务信息的空间。
-- 表目录Table Directory:记录了对应表的元数据。这样就可以将多个表的数据存储在同一个数据块中了。

 事务巢
存放了undo数据块的地址信息、被修改的数据块的信息、以及事务是否结束的信息等等。事务巢有个槽位,指向行的开始部分。
 行片段
每一行数据都是通过行片段的方式存储在数据块当中的。而行片段由行头Row Header和列数据Column Data组成;Row Header是用来记录Column Data元数据信息的,至少有3个字节,包括有:Row Overhead、Number of Columns、Cluster Key ID(if clustered)、ROWID of Chained Row Pieces(if any)、Column Length、Column Value.
· Long类型的列数据总是存储在最后
 RowID
官方文档:Database Administration – Database Concepts – Logical Storage Structures, Ctrl+F “ROWID”.
格式:数据对象号码Data Object Number(6)·文件号码Relative File Number(3)·数据块号码Block Number(6)·行号Row Number(3) -- 所以每个表空间不可能超过1023个数据文件(而实际上MAXDATAFILES已经进行了限制)。
分解RowID:DBMS_ROWID包
SYS@Orcl> SELECT rowid,
dbms_rowid.rowid_object(rowid) object_id,
dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowed) block_id,
dbms_rowid.rowid_row_number(rowid) num
FROM scott.dept;

RowID可能变化的特殊情况 – 启用了行移动:分区键更新、闪回表操作、收缩表操作;禁用了行移动:Oracle数据块实用程序导出和导入行。

数据块压缩
SYS@Orcl> CREATE TABLE <tab_name> compress as SELECT * FROM <table2_name>;
-- 数据库会将重复值替换为一个符号引用列表,存放在数据块头部。
符号 值 列 行范围


b. 扩展区
数据段被创建的时候,数据库会为数据段分配一个初始扩展区;当初始扩展区空间不够的时候,数据库会自动为该段分配一个增量扩展区(在同一表空间内,但不一定是位于连续的空间或者同一个数据文件中)。而每个段的第一个数据块则包含了该段中的扩展区目录。
当Oracle数据库开始使用扩展区时,才对它进行格式化 / 碎片整理。
 释放扩展区
段收缩:SYS@Orcl> ALTER TABLE <tab_name> SHRINK SPACE CASCADE;
将数据移动到一个新的段,或者另一个表空间;
重建或者合并索引(索引是要占用磁盘空间和表空间的);
截断表或表簇
 存储设置
优先级:段的存储参数 > 表空间的存储参数 > Oracle数据库默认值
SYS@Orcl> CREATE TABLESPACE <mytbs01> datafile ‘<path>/<datafile_name>.dbf’ size nM
AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED
[| EXTENT MANAGEMENT LOCAL UNIFORM size 20M /*默认1M*/ SEGMENT SPACE MANAGEMENT AUTO];
c. 段
段是一个表空间内某个逻辑存储结构的所有数据的扩展区集合。
 用户段
用于存储用户对象的数据,包括:表、表分区、表簇;大对象、大对象分区;索引、索引分区。当创建表、索引和分区(11g-R2)时,仅更新数据库的元数据,当需要存储数据时,才真正地分配段空间。
 临时段
典型操作有:排序(或多表连接查询、GROUP BY分组查询)、Hash哈希、合并位图。
 撤销段
Undo段空间是可以循环使用的。典型撤销操作有:Rollback回滚活动的事务、恢复已经终止的事务(实例恢复)、提供读一致性、执行逻辑闪回操作。

手动段空间管理MSSM:
INSERT操作 -> 搜索空闲列表查找可用数据块 [-> 未找到 -> 预格式化一组数据块 -> 放入空闲列表] -> 将数据写入数据块;
自动段空间管理ASSM:
INSERT操作 -> 只格式化一个位图块;
而二者的全表扫描则会读取高水位线HWM之下的所有块(造成高水位线之下、没有数据的空数据块也会被扫描,导致过高的磁盘I/O,使系统性能下降)。
· 高水位线信息会存储在段头当中。

修正高水位线:
ALTER TABLE <tab_name> MOVE;
| 删除表中部分数据时加上ALTER TABLE <tab_name> SHRINK SPACE;
/*1. 必须是自动段空间管理SEGMENT SPACE MANAGEMENT AUTO
2. 必须允许行移动:ALTER TABLE <tab_name> ENABLE ROW MOVEMENT;
3. ALTER TABLE <tab_name> SHRINK SPACE CASCADE; */
| 重建表
| 导入导出Exp / Imp
| 清空表数据时使用TRUNCATE TABLE <tab_name>;

查看段中的区、块分配的大小:
SYS@Orcl> SELECT segment_name, segment_type, extents, blocks FROM dba_segments WHERE segment_name = ‘’;
查看高水位线:
ANALYZE TABLE <tab_name> ESTIMATE STATISTICS; -- 表分析
SELECT blocks /*高水位线*/, empty_blocks, num_rows FROM user_tables WHERE table_name = ‘’;
d. 表空间
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces [– Creating Table].
 永久表空间
目的:
控制数据库数据的磁盘空间分配
控制数据库用户的磁盘空间分配
可以将单个表空间进行联机或者脱机操作,而不影响整个数据库
可以备份 / 恢复,或者使用Oracle数据泵导入 / 导出单个表空间
可以传输表空间,将数据复制或移动到另一个数据库,达到跨平台的功能

System表空间:
数据字典
关于数据库管理信息的表和视图
已经编译的存储对象,例如触发器、过程、包等等
SYSAUX辅助表空间:
存放未驻留在System表空间的数据库元数据
Undo表空间
撤销undo数据

 临时表空间
存放临时数据。
创建临时表空间
CREATE TEMPORARY TABLESPACE <temp01> tempfile ‘<path>/<tmp>.dbf’ SIZE nM;
修改默认临时表空间
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE <tmp>;
DROP TABLESPACE <temp01> [INCLUDING CONTENTS AND DATAFILES];

 Undo表空间
官方文档:Database Administration – Administrator’s Guide – Managing Undo.
Undo记录的作用:
对事务进行Rollback操作
恢复数据库
提供读一致性
使用闪回查询可以分析较早之前的数据
使用闪回特性对逻辑的错误进行恢复
show parameter undo
- undo_management: undo表空间管理方式
- undo_retention: 表示多少秒之后,undo段的数据可以被覆盖(undo段是循环使用的),但需要设置RETENTION GUARANTEE参数来保证,当undo段空间不足,时间没有到的时候,undo段的数据不能够被覆盖
- undo_tablespace: undo表空间名称

· 只能同时使用一个undo表空间。当事务还没结束时,如果在当前会话进行undo表空间切换,事务会被自动提交;如果在不同会话进行undo表空间切换,那么之前的undo表空间会处于悬挂状态,而两个会话查询出来的数据会不同。

查看undo:
show parameter undo
创建undo表空间(自动扩展):
SYS@Orcl> CREATE UNDO TABLESPACE <my_undo> datafile ‘<path>/<undo_datafile>.dbf’ size nM autoextend on;
[| CREATE DATABASE <rbdb1>
CONTROLFILE reuse

UNDO TABLESPACE <undotbs_01> DATAFILE ‘<path>/<undo_01>.dbf’; ]
修改undo:
ALTER SYSTEM …
重命名undo 表空间:
SYS@Orcl> ALTER TABLESPACE <old_name> RENAME TO <new_name>;

· 查看undo记录的具体信息
 INSERT INTO <mytab> values (…); -- 插入信息,但不提交
 SELECT s.username, r.name, t.used_ublk
FROM v$session s, v$rollname r, v$transaction t
WHERE s.saddr = t.ses_addr and r.usn = t.xidusn;
 SELECT segment_name, tablespace_name, extent_id
FROM dba_undo_extents
WHERE segment_name = ‘<r.name>’;

 表空间模式
· 只读 / 读写模式
· 联机 / 脱机状态
 大文件表空间 / 小文件表空间
小文件表空间(默认)可以包含多个(1023个)数据文件、临时文件,但文件不能像大文件表空间那么大;而大文件表空间只包含一个非常大的数据文件 / 临时文件。大文件表空间只支持ASSM(自动段空间管理)的本地管理表空间。
大文件表空间可以提高数据库的存储容量、减轻管理过多数据文件、临时文件的负担。
CREATE BIGFILE TABLESPACE <bigtbs>
DATAFILE ‘<path>/<bigtbs01>.dbf’ SIZE nG;

· 创建加密表空间
CREATE TABLESPACE <secure_space>
DATAFILE ‘<path>/<secure>.dbf’ SIZE nM
ENCRYPTION [USING ‘AES256’]
DEFAULT STORAGE(ENCRYPT);
· 创建压缩表空间
CREATE TABLESPACE … DEFAULT COMPRESS FOR OLTP …;

· Force Logging日志记录模式
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –Controlling the Writing of Redo Records.
CREATE TABLESPACE … FORCE LOGGING …;

· 管理可恢复的空间分配
-- 适用于:执行SELECT, DML, DDL操作时,[临时]表空间不足;执行SQL*Loader的导入操作,磁盘空间不足。
自动扩展关闭,表空间不足,提示:
ORA-01658: unable to create INITIAL extent for segment in tablespace <tbs_name>
使用可恢复的空间分配:
SYS@Orcl> GRANT resumable TO scott; -- 授权
SCOTT@Orcl> ALTER SESSION ENABLE RESUMABLE timeout 3600;
CREATE TABLE <tab_name> TABLESPACE <tbs_name> …
-- 不会收到错误信息,而是进入了一种挂起的状态
SYS@Orcl> ho vi $ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace/alert_<sid>.log
ORA-01658: unable to create INITIAL extent for segment in tablespace <tbs_name>
/*修改表空间(数据文件)大小*/
SELECT file_name, bytes FROM dba_data_files WHERE tablespace_name = ‘’;
ALTER DATABASE datafile ‘<path>/<mytbs01>.dbf’ RESIZE nM;
-- 可以在数据库级别进行修改。show parameter RESUMABLE_TIMEOUT
SCOTT@Orcl>: Table created.

查看表空间大小:
SYS@Orcl> SELECT sum(bytes) FROM dba_data_files WHERE tablespace_name = ‘’;
查看所有表空间的空闲空间:
SYS@Orcl> SELECT tablespace_name, count(*), sum(bytes/1024/1024) || ‘M’, max(blocks), sum(blocks) FROM dba_free_space GROUP BY tablespace_name;
查看表空间信息:
SYS@Orcl> SELECT * FROM v$tablespace;
查看数据文件的基本信息:
SELECT name, file#, status, bytes, checkpoint_change#, last_scn FROM v$datafile;
查看表空间、数据文件的信息:
SYS@Orcl> SELECT tablespace_name, file_name FROM dba_data_files;
查看默认的[临时]表空间
SELECT property_name, property_value FROM database_properties WHERE property_name like ‘DEFAULT%’;
查看是否AUTOEXTEND:
SYS@Orcl> SELECT file_name, autoextensible FROM dba_data_files WHERE tablespace_name = ‘’;
查看Scott用户拥有的段的类型、个数:
SYS@Orcl> SELECT segment_type, count(*) seg_count FROM dba_segments WHERE owner = ‘SCOTT’ GROUP BY segment_type;
查看表空间组:
SYS@Orcl> SELECT * FROM dba_tablespace_groups;
创建[临时]表空间:
SYS@Orcl> CREATE [TEMPORARY] TABLESPACE <tbs_name>
tempfile ‘<path>/<datafile_name>.dbf’ size nM;
创建非标准块大小的表空间:
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces – Specifying Nonstandard Block Sizes for Tablespaces.
SYS@Orcl> ALTER SYSTEM set db_<n>k_cache_size = nM /*2的倍数,最少4M*/ SCOPE = spfile;
SHUTDOWN IMMEDIATE
STARTUP
CREATE TABLESPACE <tbs_name> datafile ‘<path>/<datafile>.dbf’ size nM BLOCKSIZE nK;
创建[临时]表空间组:
SYS@Orcl> CREATE [TEMPORARY] TABLESPACE <tbs_name>
tempfile ‘<path>/<datafile_name>.dbf’ size Nm TABLESPACE GROUP <tbs_g_n>;
修改表空间的数据文件是否自动扩展:
SYS@Orcl> ALTER DATABASE datafile ‘<path>/<mytbs01>.dbf’ AUTOEXTEND on next 1M maxsize unlimited [| AUTOEXTEND OFF];

改变表空间大小:
- 增加数据文件:
官方文档:Database Administration – Administrator’s Guide –Managing Datafiles and Tempfiles – Creating Datafiles and Adding Datafiles to a Tablespace.
SYS@Orcl> ALTER TABLESPACE <tbs_name> ADD DATAFILE ‘<path>/<mytbs01>.dbf’ size nM;
- 修改数据文件大小:
官方文档:Database Administration – Administrator’s Guide –Managing Datafiles and Tempfiles – Changing Datafile Size.
SYS@Orcl> SELECT file_name, bytes FROM dba_data_files WHERE tablespace_name = ‘’;
ALTER DATABASE datafile ‘<path>/<mytbs01>.dbf’ RESIZE nM;
ALTER DATABASE datafile ‘<path>/<mytbs01>.dbf’ AUTOEXTEND on next 1M maxsize unlimited;

移动用户表空间的数据文件:
官方文档:Database Administration – Administrator’s Guide –Managing Datafiles and Tempfiles – Renaming and Relocating Datafiles.
SYS@Orcl> SELECT file_name FROM dba_datafiles WHERE tablespace_name = ‘’;
ALTER TABLESPACE <tbs_name> OFFLINE;
ho mv <old_path>/<datafile>.dbf <new_path>/<datafile>.dbf
ALTER TABLESPACE <tbs_name> RENAME DATAFILE ‘<old_path>/<datafile>.dbf’ to ‘<new_path>/<datafile>.dbf’;
ALTER TABLESPACE <tbs_name> ONLINE;
SELECT file_name FROM dba_datafiles WHERE tablespace_name = ‘’;
-- 数据库是在open状态下完成的
移动系统表空间的数据文件:
官方文档:Database Administration – Administrator’s Guide –Managing Datafiles and Tempfiles – Renaming and Relocating Datafiles.
SYS@Orcl> SELECT file_name FROM dba_datafiles WHERE tablespace_name = ‘SYSTEM’;
SHUTDOWN IMMEDIATE
ho mv <old_path>/<datafile>.dbf <new_path>/<datafile>.dbf
STARTUP MOUNT
ALTER DATABASE RENAME DATAFILE ‘<old_path>/<datafile>.dbf’ to ‘<new_path>/<datafile>.dbf’;
SELECT name FROM v$datafile;
ALTER DATABASE OPEN;
SELECT file_name FROM dba_datafiles WHERE tablespace_name = ‘SYSTEM’;

修改用户的临时表空间为临时表空间组:
SYS@Orcl> ALTER USER <u01> TEMPORARY TABLESPACE <tbs_g_n>;

将表空间置为只读 / 读写:
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –Using Read-Only Tablespaces.
SYS@Orcl> ALTER TABLESPACE <tbs_name> READ ONLY [| READ WRITE];
将表空间置为联机 / 脱机:
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –Altering Tablespace Availability.
SYS@Orcl> ALTER TABLESPACE <tbs_name> OFFLINE NORMAL [| ONLINE];
将数据文件置为联机 / 脱机:
SYS@Orcl> SHUTDOWN IMMEDIATE
STARTUP MOUNT
ALTER DATABASE ARCHIVELOG; -- 归档模式下
ALTER DATABASE open;
ARCHIVE LOG LIST
ALTER DATABASE datafile ‘<datafile>.dbf’ OFFLINE; -- 脱机
ALTER DATABASE datafile ‘<datafile>.dbf’ ONLINE; -- 联机
ORA-01113: file n needs media recovery
ORA-01110: data file n: ‘<path>/<datafile>.dbf’
RECOVER DATAFILE n;
ALTER DATABASE datafile ‘<datafile>.dbf’ ONLINE;

重命名表空间:
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –Renaming Tablespaces.
SYS@Orcl> ALTER TABLESPACE <users> RENAME TO <users_tbs>;
将表空间加入到表空间组:
SYS@Orcl> ALTER TABLESPACE <tbs_name> TABLESPACE GROUP <tbs_g_n>;
-- 如果要将表空间剔除出表空间组,那么就要删除该表空间。
删除表空间:
官方文档:Database Administration – Administrator’s Guide – Managing Tablespaces –Dropping Tablespaces.
SYS@Orcl> DROP TABLESPACE <tbs_name> INCLUDING CONTENTS AND DATAFILES [CASCADE CONSTRAINTS /*删除System表空间*/];
e. 逻辑空间管理
本地管理表空间
数据库使用表空间本身中的位图来管理扩展区,这个位图位于数据文件头部。

自动段空间管理(ASSM)
也是使用位图管理空间。简化管理,只需设置PCTFREE参数即可。建议使用。
如果是联机事务处理系统(On-Line Transaction Processing),那么DML操作可能会偏向频繁,所以需要预留足够的PCTFREE空闲空间。PCTFREE值太小 -> UPDATE -> 行迁移 -> I/O增加 -> 系统性能下降;PCTUSED值太小 -> DELETE少量数据 -> INSERT大量数据 -> 行链接 -> I/O增加 -> 系统性能下降(建议列数不要超过255,避免行链接)。
查看PCTFREE、PCTUSED:
SYS@Orcl> SELECT pct_free, pct_used, table_name FROM dba_tables;
查看行迁移、行链接:
SYS@Orcl> GRANT connect, resource TO <u01>;
u01@Orcl> @$ORACLE_HOME/rdbms/admin/utlchain.sql
ANALYSE TABLE <tab_name> LIST CHAINED ROWS;
SELECT * FROM chained_rows;
此外,当进行INSERT / UPDATE操作时,有足够的可用空间,但空间被碎片化,以至于行片段不能插入到某个连续的区域时,Oracle才会自动合并数据块的可用空间,避免影响系统性能。

手动段空间管理
MSSM使用空闲列表的链表来管理段的可用空间,这个空闲列表会跟踪位于高水位线以下的数据块。所谓高水位线,就是曾被使用过和未被使用过的数据块之间的分界线。需要配置PCTFREE, PCTUSED, FREELISTS, FREELIST GROUPS等参数。当已经使用的空间 > PCTUSED, 或者空闲空间 < PCTFREE都不能插入数据,只能update。而且当数据块被使用时(INSERT, DELETE),才会剔除出空闲列表,或者添加到空闲列表开头。
一个对象可能有多个空闲列表,n个进行DML操作的会话可以有n个空闲列表,以此来减少争用。而空闲列表实际上就是一个用来管理空闲列表的列表。但空闲列表、空闲列表组的空间开销可能非常显著。
2. 实例
-- 至少一个
定义:管理数据库文件的一组内存结构。包含系统全局区SGA(给后台进程和服务器进程共享的内存区域)和一组后台进程。实例可以独立于数据库文件存在(startup nomount的时候分配了内存空间、启动了后台进程,但是数据库还没有加载上去)。
A. 内存结构
a. SGA (System Global Area / Shared Global Area)
官方文档:Database Administration – Database Concepts – Memory Architecture – Introduction to Oracle Database Memory Structures.
内存存储以下信息:程序代码、会话信息、程序执行所需的信息、进程共享和通信的信息(例如锁等)、缓冲的信息。

一组包含了Oracle数据库数据(冯·诺依曼的思想:不能直接操作磁盘中的数据文件,而是应该把它读取到内存中进行操作),以及实例控制信息(管理实例)的共享内存结构。
SGA的大小由sga_target参数(SYS@Orcl> show parameter sga; )所决定,但不能超过sga_max_size参数的值。SGA包括以下结构:
数据高速缓冲区Data Buffer Cache
定义:缓存从数据库读出的数据块,共享给其它服务器进程在里面读取、修改数据。
作用:优化I / O.
 保留缓冲区 – db_keep_cache_size参数。保留内存中很有可能被重用的对象。
 循环缓冲区 – db_recycle_cache_size参数。保留被重用机会不大的对象,会被写回到数据文件,然后踢出内存。
 默认缓冲区 – db_cache_size参数。保留缓冲区和循环缓冲区以外的部分。该池始终存在。

 标准块的高速缓冲区:db_cache_size参数;非标准块的高速缓冲区:db_<2^n>k_cache_size参数。数据块大小默认8k (SYS@Orcl> show parameter block; -> db_block_size参数)。
查看操作系统块大小:[root@RedQueen ~]# /sbin/tune2fs -l /dev/sda1 | grep Block



根据缓冲区数据块的状态,可以将数据高速缓冲区可划分成:
脏缓冲区 – 发生DML操作(Insert, Delete, Update)时,对应缓冲区的内容会与数据文件不一致,这样的缓冲区叫做脏缓冲区。相对应地,会有一个用来记录脏缓冲区情况的脏列表,当脏列表达到一定阀值的时候,Oracle会将脏缓冲区的内容写入数据文件;
干净的缓冲区 – 已经把数据写回到磁盘了的;
未使用的缓冲区 – 没有使用过的。
缓冲区数据块的access mode:
Free (unpinned) – 脏缓冲区的内容被写入数据文件之后;
Pinned (busy) – 正在使用的缓冲区。

Buffer mode:
Current mode – 读取没有被修改过的数据;
Consistent mode – 一致性读。会话A修改数据a,但没有提交;会话B读取数据a,则依然会是修改之前的样子。

LRU(Latest Recently Used)算法
热端头部 -> -> -> 插入列表 冷端头部 -> -> ->
每个内存数据块(buffer)头部都包含有block number, touch count和timestamp.
Touch count表示在每3秒钟内,”数据块被读入内存”或者”touch count被reset”之后,被touch的次数。
 LRU列表里的数据每被使用1次,这个数据的计数器count就+1.
 当这个内存数据块到达冷端的末端时,如果touch count > 2, 它会被移动到热端,同时touch count清零;否则touch count <= 2就会被写入数据文件、踢出内存。

清空数据库高速缓冲区
SYS@Orcl> ALTER SYSTEM FLUSH buffer_cache;
重做日志缓冲区Redo Log Buffer
当进行DML (Insert, Delete, Update)以及DDL(Create, Alter, Drop)操作时,Oracle会将重做项信息(属于元数据信息,并非具体数据信息)记录到重做日志缓冲区,从而可以实现对实例的恢复(并非对介质/*数据库文件*/的恢复)。它是循环使用的一个缓冲区,使用”SYS@Orcl> show parameter log_buffer; “可以查询重做日志缓冲区大小。
共享池Shared Pool
官方文档:Database Administration – Database Concepts – Memory Architecture.
共享池由库高速缓存,以及数据字典缓冲区组成。大小由shared_pool_size参数决定。
 库高速缓存 – 分为共享SQL区、私有SQL区、共享PL/SQL区、变量控制结构。
作用:
存放共享的SQL、PL/SQL;
采用LRU算法;
避免相同代码再次硬解析;
ORA-04031表面共享池不够用。
不同SQL的语句文本、解析树、执行计划(Oracle为执行SQL语句,产生对应的优化了的执行步骤)存放在不同的上下文区(Context Area)。当客户端在运行SQL之前,服务器进程会先检查是否存在对应语句的上下文区。可以使用原本的执行计划叫做软解析,不可以使用的叫做硬解析(需要占用CPU和I/O资源)。
语句文本、大小写、赋值变量都相同的,才是完全相同的SQL语句。OLTP(Online Transaction Processing, 例如银行系统)可以考虑通过合理设置”Scott@Orcl> ALTER SESSION SET cursor_sharing = exact / similar / force”来提高执行计划的重用效率;OLAP(Online Analytical Processing, 例如数据仓库)则不需要,因为SQL的解析对于SQL的执行来说,花费的代价几乎可以忽略。
查看共享池性能状况:
SELECT namespace, gets, gethits,
round(gethitratio * 100, 2) gethit_ratio, pins /*执行次数*/, pinhits,
round(pinhitratio * 100, 2) pinhit_ratio, reloads /*次数过多则表明对象无效*/, invalidations /*无效的对象*/
FROM v$librarycache; -- 重载率 > 0,考虑是否需要调整shared_pool_size.
SELECT sum(pins), “Executions” sum(reloads) “Cache Misses while Executing”,
round(sum(reloads) / sum(pins) * 100, 2) AS “Reload Ratio %”
FROM v$librarycache;
- 参考增大共享池的建议:
SELECT shared_pool_size_for_estimate estimate_size, shared_pool_size_factor size_factor, estd_lc_size, estd_lc_memory_objects obj_count, estd_lc_time_saved_factor save_factor
FROM v$shared_pool_advice;
共享池调优性能视图:
v$sgastat, v$librarycache, v$sql, v$sqltext, v$db_object_cache.
共享池调优重要参数:
Shared_pool_size, open_cursors, session_cached_cursors, cursor_space_for_time, cursor_sharing, shared_pool_reserved_size.
 数据字典缓冲区 – 保存数据字典信息,因为基本上做任何操作都会用到数据字典。
查看数据字典缓存命中率:
SELECT round( (1 - sum(getmisses) / (sum(gets) + sum(getmisses)) ) * 100, 1) “Hit Ratio”,
round(sum(getmisses) / sum(gets) * 100, 1) “Misses Ratio”
FROM v$rowcache WHERE (gets + misses) <> 0;
SELECT round( (100 * sum(getmisses) / decode(sum(gets), 0, 1, sum(gets)) ), 2) Getmiss_ratio
FROM v$rowcache; -- 整个数据字典的缺失率
/*命中率 >= 95%;缺失率 < 15%、常用数据字典对象的缺失率 < 2%才是正常的*/
 SQL语句执行过程:
i. 语法检查、语义检查(对象是否存在、权限等);
ii. 对SQL语句进行hash,得到hash值(可以查询v$sql, v$sqlarea, v$sqltext视图);
iii. 如果共享池中存在相同的hash值,进一步判断是否需要硬解析,是 – 跳到步骤v;
iv. 将新的SQL语句与旧的进行逐个字符的比较,如果通过,软解析 – 跳到步骤vi;
v. 硬解析,生成执行计划;
vi. 执行代码,返回结果集。

清空共享池缓存(执行计划等):
SYS@Orcl> ALTER SYSTEM FLUSH SHARED_POOL;
Java池Java Pool
java_pool_size参数,可选的内存区域,供Java代码、以及JVM的数据使用。
大池Large Pool
官方文档:Database Administration – Database Concepts – Memory Architecture

large_pool_size参数,可选的内存区域,包括有:UGA(User Global Area) /*存放用户Session的内存区域*/、请求队列、响应队列等,供一次性大量的内存分配使用,例如:
共享服务器(shared server)和 Oracle XA 接口(一个事务与多个数据库交互时使用的接口)使用的会话内存
Oracle 备份与恢复操作
I/O 服务进程

 专有服务器模式 – 每个客户端都分配且只分配一个服务器进程与之通信,这个服务器进程为客户端所专用。服务器进程将进程的特定信息、以及UGA都存储在PGA当中。
 共享服务器模式 – 客户端不是直接与服务器进程进行连接通信。而是连接到服务器的监听器之后,监听器将n个客户端连接到1个调度器进程,调度器进程接收客户端的请求,并将请求放入到大池的请求队列里,由共享服务器进程访问大池的请求队列,并完成请求。共享服务器进程将结果放到响应队列,调度器进程监听响应队列,并将结果返回给客户端。
共享服务器模式也有自己的PGA,但是会话的UGA并不像专有服务器模式那样存储在PGA中,而是存储在SGA的大池当中。
共享服务器模式的优点:i. 减少操作系统进程、线程数,避免上下文的频繁切换,大大提高效率;ii. 避免并发度过大。

客户端请求专有服务器模式连接:
在CONNECT_DATA=(SERVER_NAME=<instance_name>)后添加“(SERVER=DEDICATED)”
查看有多少个会话使用共享服务器模式进行连接:
SELECT count(*) FROM v$circuit;
-- 通过系统验证方式登录的,使用的都是专有服务器模式。
查看是否处于共享服务器模式:
SELECT saddr, program, server FROM v$session;
[| SELECT * FROM v$shared_server; ]
-- “SELECT * FROM v$dispatcher; ”只能说明配置了dispatcher参数,不能说明是否启用的共享服务器模式。
共享服务器模式需要设置以下参数(使用ALTER SYSTEM … 或者修改pfile):
· SYS@Orcl> ALTER SYSTEM set shared_servers = 4 scope = both /*必须设置。默认为1,专有服务器模式下是0 */;
· SYS@Orcl> ALTER SYSTEM set dispatchers = ‘(protocol=tcp)[(serv=网络服务名 /*sqlplus scott/scott@网络服务名,否则可能会登陆失败*/)(list=网络服务名 /*sqlplus scott/scott@网络服务名*/)(poo=on /*启用共享池*/)(con=60 /*每个调度进程最大连接数*/)(sess=1000 /*每个调度进程最大会话数*/)](dispatchers=9)’ scope = both /*必须设置。*/
· max_shared_servers
· shared_server_sessions
· max_dispatchers
流池Stream Pool
streams_pool_size参数,可选的内存区域,供流复制的时候使用。
固定的SGA
f. PGA
g. UGA (User Global Area)
存放用户Session的内存区域,存放的信息包括有会话的变量、以及OLAP (Online Analytic Processing)池

/* TBC */ 软件代码区Software code areas

B. 进程结构
用户通过客户端产生客户端进程,然后服务器分配服务器进程与之相关联、进行通信,从而连接到实例。有了这个服务器进程之后,就会分配一个自己私有的会话内存区(程序全局区PGA)。并且客户端进程是通过服务器进程间接地来对数据库当中的数据进行访问、操作的。而后台进程是用来监控数据库的使用情况的。
十四、 内存管理
官方文档:
Database Administration – Database Concept – Memory Architecture;
Database Administration – Administrator’s Guide – Managing Memory.

AMM(Automatic Memory Management) – 默认
ASMM(Automatic Shared Memory Management) – 仅设置SGA的目标大小(memory_target, 动态参数。”ALTER SYSTEM ... “)、最大大小(memory_max_target, 静态参数),但SGA的每个组件仍然自动调整大小(”SHOW PARAMETER memory; “);
Oracle建议使用AMM配置新的数据库,然后监视内存管理效果,后面切换到ASMM。这样能控制SGA大小,但仍让Oracle管理SGA每个组件的大小。





1. 参数设置方式
A. memory_target > 0
AMM.
a. 同时设置了sga_target和pga_aggregate_target
sga_target和pga_aggregate_target分别是指sga和pga的最小值。如果不想使用,可以将他们设置为0。
memory_target 的值范围是:从sga_target + pga_aggregate_target到memory_max_target
b. 设置了sga_target,未设置pga_aggregate_target
Oracle仍自动调整这两个参数。但pga_aggregate_target以memory_target - sga_target开始。
c. 未设置sga_target,但设置了pga_aggregate_target
Oracle仍自动调整这两个参数。但sga_target以min(memory_target - pga_aggregate_target, sga_max_target)开始。
d. 未设置sga_target和pga_aggregate_target
Oracle自动调整sga_target和pga_aggregate_target。其中的60%用于sga,40%用于pga。
B. memory_target = 0
a. sga_target > 0
ASMM.
Oracle自动调整sga组件,无论是否有设置,pga都会被自动调整。
b. sga_target = 0
手动。
必须设置sga组件大小,Oracle自动调整pga。
2. AMM切换到ASMM
A. 查看当前内存管理模式
SHOW PARAMETER sga; -- if sga_target == 0, then AMM;
B. 查看SGA和PGA大小
/*查看SGA实际大小*/
SELECT component, current_size/1024/1024 Current_size
FROM v$memory_dynamic_components
WHERE component in (‘SGA_TARGET’, ‘PGA_TARGET’);
C. 切换到ASSM
SYS@Orcl> SHOW PARAMETER memory
ALTER SYSTEM SET memory_target = 0;
SHOW PARAMETER sga; -- sga有具体值了
D. 查看SGA各个组件区大小
SELECT pool, sum(BYTES)/1024/1024 Mb
FROM v$sgastat
GROUP BY pool;
/*查看Database Buffer Cache分配情况*/
SELECT pool, name, bytes/1024/1024 Mb
FROM v$sgastat WHERE pool is null;

P.S.
a. log_buffer、以及fixed_sga并不是动态管理的,而是有一个固定值的。
b. memory_target = sga_target + pga_aggergate_target.
3. ASMM切换到AMM
SYS@Orcl> ALTER SYSTEM SET sga_target = 0;
ALTER SYSTEM SET pga_aggregate_target = 0;
ALTER SYSTEM SET memory_target = <X>;
4. ASMM切换到手动
SELECT name, bytes/1024/1024 FROM v$sgainfo;
SYS@Orcl> ALTER SYSTEM SET sga_target = 0;
ALTER SYSTEM SET memory_target=0;
SHOW PARAMETER pool;
SHOW PARAMETER cache;
5. 手动切换到ASMM
A. 查看SGA大小
SELECT (
(SELECT sum(value) FROM v$sga) - (SELECT current_size FROM v$sga_dynamic_free_memory)
) “sga_target” FROM dual;
B. 修改sga_target值
SYS@Orcl> ALTER SYSTEM SET sga_target = <sga_target>;
C. 修改SGA各组件的值
SYS@Orcl> ALTER SYSTEM SET streams_pool_size = 0;
ALTER SYSTEM SET shared_pool_size = 0;
ALTER SYSTEM SET large_pool_size = 0;
ALTER SYSTEM SET java_pool_size = 0;
ALTER SYSTEM SET db_cache_size = 0;
6. 禁用ASMM
ALTER SYSTEM SET sga_target = 0;
7. 动态性能视图
查看组件的状态
v$memory_dynamic_components
通过比较,寻找数据库最佳的内存大小设置
v$memory_target_advice
其他关于内存分配的视图
v$sga、v$sgastat、v$sga_dynamic_free_memory
十五、 Oracle目录结构
$ORACLE_BASE=/u01/app/oracle
$ORACLE_HOME=$ORACLE_BASE/product/11.2.0/db_1
1. $ORACLE_BASE/admin/
$ORACLE_BASE/admin/adump 审计文件
$ORACLE_BASE/admin/dpdump 数据泵目录对象
2. $ORACLE_BASE/diag/rdbms/orcl/orcl/
$ORACLE_BASE/diag/rdbms/orcl/orcl/ rdbms警告文件、跟踪文件、核心转储文件、健康监视报告
$ORACLE_BASE/diag/rdbms/orcl/orcl/hm/ 健康监视报告
$ORACLE_BASE/diag/rdbms/orcl/orcl/metadata/ 元数据信息
$ORACLE_BASE/diag/rdbms/orcl/orcl/cdump/ 核心转储文件

3. $ORACLE_BASE/fast_recovery_area/
$ORACLE_BASE/fast_recovery_area/ 闪回恢复区,和恢复有关的信息:例如归档文件、Rman备份的数据信息、闪回日志(备份信息优先存储,而日志则不会)
$ORACLE_BASE/fast_recovery_area/orcl/ control02.ctl
$ORACLE_BASE/fast_recovery_area/ORCL/ 在线日志

4. $ORACLE_BASE/oradata/$ORACLE_SID/
$ORACLE_BASE/oradata/$ORACLE_SID/ 数据库文件:control01.ctl、日志文件.log、数据文件.dbf

5. $ORACLE_HOME/
$ORACLE_HOME/ Oracle软件的所有文件(系统文件)
$ORACLE_HOME/sqlplus/ SQLPlus工具相关信息
$ORACLE_HOME/sqlplus/admin/ 一些脚本文件,例如glogin.sql (SQLPlus启动时会读取)
$ORACLE_HOME/bin/ 所有的命令文件,/home/user/.bash_profile -> export PATH=$PATH:$ORACLE_HOME/bin
$ORACLE_HOME/network/admin/ 网络配置,listener.ora网络配置文件
$ORACLE_HOME/rdbms/admin/ 脚本文件
$ORACLE_HOME/dbs/ 参数文件、口令文件
十六、 网络配置
Directory: $ORACLE_HOME/network/admin/

官方文档:Database Administration – Network Management [– Oracle Net Listener Parameters (listener.ora)].
配置方法:netca;netmgr;修改配置文件。
[Oracle@RedQueen ~]$ netmgr
- Service Naming选项 -> tnsnames.ora:
Host: <hostname / ifconfig – IP address>
- Listeners选项 -> listener.ora:
Net Service Name: <random> -- sqlplus scott/scott@<random>
协议必须与监听器的一致
Service Name: show parameter service_name
/*静态注册:Listening Locations下拉列表 -> Database Service:
Global Database Name: “show parameter service_name”
Oracle Home Directory: <$ORACLE_HOME>
SID: “show parameter instance_name”(小写)*/
注释:listener.ora的service_name可以有多个(“ALTER SYSTEM set service_names = ’<orcl01>,<orcl02>’; ” -> “show parameter service_name”)(其实address也可以有多个,例如需要多个端口的时候);但tnsnames.ora当中的service_name必须要与其中一个相匹配,或者跟数据库实例名相同。

注册具体是指将实例名“show parameter instance_name”和服务名“show parameter service_name”注册到监听器。
动态注册:在实例启动的时候,PMON进程根据参数文件中的instance_name, service_name两个参数将实例、服务动态注册到listener当中。动态注册默认只注册到默认监听器上。动态注册也分为自动注册和手动注册“ALTER SYSTEM REGISTER; ”;静态注册与实例的启动和关闭是无关的。
· lsnrctl status -> READY: 动态注册;UNKNOWN: 静态注册。

· 重启网络服务:
[Oracle@RedQueen ~]$ lsnrctl stop
SYS@Orcl> ALTER SYSTEM REGISTER;
[Oracle@RedQueen ~]$ lsnrctl start
lsnrctl status
· 非默认端口
使用动态监听才需要修改,静态监听的时候要为空。
show parameter local_listener
ALTER SYSTEM set local_listener = <random> -- 网络服务名
-- 但只能是与该监听器(可能只有对应的这个监听器生效)的protocal、host(IP address)、port都相同的客户端(tnsnames.ora)才能连接进来。
十七、 数据库对象
Table, view, sequence, index, synonym
伪列 – 官方文档:Pseudocolumns
十八、 数据类型
官方文档 - Database Administration -> SQL Language Reference -> Basic Elements of Oracle SQL -> Data Types.

NVARCHAR2(size) -- Unicode char通用字符集, VARCHAR2(size), CHAR(size), NUMBER(精度,小数), LONG -- 可变字符型, RAW and LONG / RAW -- 二进制, CLOB -- 字符型, BLOB -- 二进制, BFILE -- 二进制, ROWID -- 64位行唯一地址标识, DATE, TIMESTAMP, INTERVAL YEAR TO MONTH -- 储存间隔多少年多少月, INTERVAL DAY TO SECOND -- 储存间隔多少天、小时、分钟、秒
时区:DATE -- 日期和时间; TIMESTAMP -- 不保存时区和地区; TIMESTAMP WITH TIME ZONE -- 默认会话时区; TIMESTAMP WITH LOCAL TIME ZONE – 以数据库时区时间保存,以会话时区时间返回; INTERVAL YEAR TO MONTH; INTERVAL DAY TO SECOND
十九、 约束类型
1. 定义约束
列级定义约束 -- NOT NULL 只能定义在列级:
CREATE TABLE table_name
(col1 DATATYPE CONSTRAINT column_constraint CONSTRAINT_TYPE [, col2…]);
表级定义约束(建议) -- 唯一性约束定义多列必须在表级定义:
CREATE TABLE table_name (col1 DATATYPE [, col2…]
CONSTRAINT table_constraint CONSTRAINT_TYPE (colN));

NOT NULL, UNIQUE -- 可以有空值, PRIMARY KEY -- 逻辑ROWID, 通过索引实现, 索引名称等于主键名称, 可以联合主键, FOREIGN KEY (col1) REFERENCES table_name(colA) ON DELETE CASCADE / ON DELETE SET NULL -- 使用触发器进行级联更新, CHECK -- 不允许使用伪列,不能调用SYSDATE, UID, USER, USERENV函数,不能涉及到其它关联行查询
默认格式:SYS_Sn
2. 添加约束
ALTER TABLE table_name
ADD [CONSTRAINT constraint_name] constraint_type (col)
[DEFERRABLE | NOT DEFERRABLE] [INITIALLY DEFERRED /*违反约束, 全部回滚, 事务原子性*/ | INITIALLY IMMEDIATE];
ALTER TABLE table_name MODIFY (col [CONSTRAINT constraint_name] NOT NULL); -- NOT NULL
3. 丢弃约束
ALTER TABLE table_name
DROP CONSTRAINT constraint_name [CASCADE丢弃列关联的外键约束];
4. 禁用约束
ALTER TABLE table_name
DISABLE | ENABLE CONSTRAINT constraint_name [CASCADE /* DISABLE相关联的约束*/]
5. 延迟约束
ALTER TABLE table_name
ADD [CONSTRAINT constraint_name] constraint_type (col)
[DEFERRABLE | NOT DEFERRABLE] [INITIALLY DEFERRED /*违反约束, 全部回滚, 事务原子性*/ | INITIALLY IMMEDIATE];

ALTER SESSION SET CONSTRAINTS = IMMDIATE;
6. 修改约束名字
ALTER TABLE table_name RENAME CONSTRAINT old_constraint_name TO new_constraint_name;
二十、 读一致性与SCN
1. 读一致性
作用:DML操作不再阻塞SELECT.
User A -> update -> 旧的数据 -> undo段(SCN m, m > n) -> 还没提交
-> User B -> SELECT (SCN n) -> 数据块块头事务巢 -> (SCN > m) -> changed data before commit -> undo段

User A -> SELECT * from tab2s FOR UPDATE;
-> User B -> update -> 没有响应
User A -> ROLLBACK;
-> User B -> No rows updated.
2. SCN
SCN(System Change Number)是Oracle的一个重要机制,用来解决意外down机的问题,尤其体现在数据恢复Data Guard、Streams流复制、RAC各节点之间的同步等功能中。SCN主要分为4种:
· 系统检查点System Checkpoint SCN
存放在控制文件当中。查询方式:SELECT checkpoint_change# FROM v$database; -- 可以发现返回的结果集只有一条记录,它是针对整个数据库的;
· 数据文件检查点Datafile Checkpoint SCN
也是存放在控制文件当中。查询方式:SELECT name, checkpoint_change# FROM v$datafile; -- 1个数据文件,就有返回1条记录;
· 结束SCN
存放在控制文件当中,用于在数据库启动过程中,检查是否需要做实例恢复Instance Recovery。查询方式:SELECT name, last_change# FROM v$datafile; -- 1个数据文件,就有返回1条记录;而且在数据库正常运行当中的时候,last_change#是一个无穷大的数字或者是null;
· 开始SCN
保存在数据文件头部当中,用于在数据库启动过程中,检查是否需要做介质恢复Media Recovery。查询方式:SELECT name, checkpoint_change# FROM v$datafile_header;
注释:
除了数据文件检查点Datafile Checkpoint SCN之外,之所以还需要一个系统检查点System Checkpoint SCN,是为了区分控制文件是否为当前(最新的)控制文件。
当Start SCN号(也就是数据文件头部那个)超过了系统检查点System Checkpoint SCN号(控制文件当中那个)时,那就说明控制文件不是最新状态,因此需要RECOVER DATABASE USING BACKUP CONTROLFILE;
A. SCN与数据库启动、关闭
· 实例恢复Instance Recovery由SMON进程自动完成,不需要人为干预;
· Oracle会首先检查是否需要Media Recovery,然后再检查Instance Recovery;
· 数据库正常关闭的时候,会触发一个检查点checkpoint,将控制文件、日志文件、数据文件的SCN号保持一致。
B. Oracle将数据写入数据文件的过程
i. 事务开始;
ii. 在数据库高速缓冲区Database Buffer Cache中查找需要的数据块,如果没有,就从数据文件中载入数据库高速缓冲区Database Buffer Cache;
iii. 事务修改数据库高速缓冲区Database Buffer Cache的数据块,将该数据标识为“脏数据”,并写入Redo日志缓冲区;
iv. 事务提交,LGWR进程将Redo日志缓冲区的“脏数据”记录写入Redo日志文件;
v. 当发生检查点的时候,CKPT进程更新所有数据文件的头部信息,而DBWn进程则将数据库高速缓冲区Database Buffer Cache中的脏数据写入数据文件当中。
注释:
在步骤iv的事务提交之后,会在Redo日志文件产生一条Redo记录,同时系统会为其提供一个最新的SCN。
如果这条记录在Redo日志文件中被清空(也就是发生日志切换,或者发生checkpoint的时候,这些脏数据已被写入数据文件当中),那么这个SCN会被记录为Redo日志文件的“low SCN”。之后写入的Redo日志文件的SCN就是Next SCN了。
当发生日志文件切换、或者checkpoint的时候(步骤v),从low SCN到Next SCN之间的所有Redo记录所对应的数据,就会被DBWn进程写入数据文件当中,而CKPT进程则将所有的数据文件头部的Start SCN更新为Next SCN的值。与此同时,系统检查点System Checkpoint SCN和数据文件检查点Datafile Checkpoint SCN也会更新为Next SCN的值。

 查看当前SCN
SYS@Orcl> SELECT current_scn FROM v$database;
二十一、 权限与概要文件
1. 权限
A. 系统权限
GRANT <sys_privilege>[, <sys_privilege2> … ]
TO <user> | <role> | PUBLIC[, <user2> | <role2> … ]
[WITH ADMIN OPTION];

REVOKE <sys_privilege>[, <sys_privilege2> … ]
FROM <user> | <role> | PUBLIC[, <user2> | <role2> … ];
-- 系统权限在回收时不会被级联回收

查看系统权限:
SELECT * FROM user_sys_privs;

系统权限可以分为三类:
针对系统级别或者数据库级别的操作,例如:CREATE SESSION, CREATE TABLESPACE;
允许用户在自己模式内的对象管理,例如:CREATE TABLE;
允许用户在任何模式内的对象管理,例如:CREATE ANY TABLE。

NAME 权限

SYSOPER - STARTUP, SHUTDOWN
- ALTER DATABASE: open, mount, back up
- ARCHIVELOG, RECOVERY
- CREATE SPFILE
- restrict session
SYSDBA - STARTUP, SHUTDOWN
- ALTER DATABASE: open, mount, back up, change character set
- CREATE DATABASE
- ARCHIVELOG, RECOVERY
- CREATE SPFILE
- restrict session
ALTER DATABASE
ALTER SYSTEM
AUDIT SYSTEM - alter database
- alter system
- “audit” statement
CREATE [PUBLIC] | DROP PUBLIC DATABASE LINK Create / drop the private / public database links
GRANT ANY PRIVILEGE grant any system privilege
GRANT ANY OBJECT PRIVILEGE owner@Orcl> GRANT ANY OBJECT PRIVILEGE TO <u01>
ADMINISTER SQL MANAGEMENT OBJECT plan history, SQL performance
CREATE USER - assign quotas on any tablespace
- set default and temp tablespace
ALTER USER - change another user’s password
- assign quotas on any tablespace
- set default and temp tablespace
- assign a profile or default roles
DROP USER drop user
CREATE

| ALTER
| RESTRICTED SESSION connect to the database | alter session | logon after instance started using the SQL*Plus STARTUP RESTRICT statement
CREATE
| ALTER ANY
| DROP ANY
| GRANT ANY ROLE create / alter / drop / grant [any] roles
CREATE | ALTER | DROP PROFILE create / alter / drop profile
CREATE | ALTER | DROP ROLLBACK SEGMENT create / alter / drop rollback segment
FLASHBACK ANY TABLE flashback query on any table, view, or materialized view in any schema.
not needed to execute the DBMS_FLASHBACK procedure.
FLASHBACK ARCHIVE ADMINISTER create / alter / drop any flashback data archive
RESUMABLE enable resumable space allocation
ANALYZE ANY analyze any table, cluster or index in any schema
CREATE | ALTER | DROP TABLESPACE create | alter | drop tablespaces
MANAGE TABLESPACE - tablespace online / offline
- begin / end tablespace backups
UNLIMITED TABLESPACE - unlimited amount of any tablespace
- CANNOT grant it to Roles
CREATE [ANY]
| ALTER ANY
| INSERT ANY
| DELETE ANY
| SELECT ANY
| UPDATE ANY
| DROP ANY TABLE create / alter any table or view [in any schema]
insert rows into tables and views in any schema
delete rows from tables, table partitions, or views in any schema
查询数据库内的任何表
修改数据库内的任何表
drop or truncate tables or table partitions in any schema
BACKUP ANY TABLE use exp tools to backup
CREATE [ANY] | DROP [ANY] VIEW create / drop views [in any schema]
UNDER ANY VIEW create subviews under any object views
MERGE ANY VIEW merge views in any schema
CREATE [ANY]
| ALTER ANY
| DROP ANY MATERIALIZED VIEW create / alter / drop materialized view [in any schema]
CREATE ANY | ALTER ANY | DROP ANY INDEX create any / alter any / drop any index
CREATE
[ANY]

| [EXTERNAL] JOB - create jobs, schedules, or programs
- create, alter, or drop jobs, schedules, or programs -- extremely powerful privilege
- create an executable scheduler job in the grantee’s schema,
which runs on the operating system
CREATE [ANY]
| ALTER [ANY]
| DROP [ANY] TRIGGER create / enable, disable or compile / drop triggers [in any schema]
CREATE [ANY]
| ALTER ANY
| DROP ANY
| EXECUTE ANY PROCEDURE create / alter / drop / execute stored procedure, functions, and packages [in any schema]
CREATE ANY | DROP ANY DIRECTORY create / drop directory -- database objects
CREATE [ANY]
| ALTER ANY
| DROP ANY
| SELECT ANY
| UPDATE ANY CUBE create / alter / drop / query and view / update OLAP cube [in any schema]
CREATE [ANY]
| DROP ANY
| UPDATE ANY CUBE BUILD PROCESS create / drop / update OLAP cube build process [in any schema]
CREATE [ANY] | [PUBLIC]
| DROP [ANY] | [PUBLIC] SYNONYM create private | public synonym [in any schema]
CREATE [ANY]
| ALTER ANY
| DROP ANY
| SELECT ANY SEQUENCE create / alter / drop / refer to sequence [in any schema]
CREATE [ANY] | DROP ANY LIBRARY create / drop external procedure or function libraries [in any schema]
COMMENT ANY TABLE comment on any table, column or view in any schema
注释:
· 系统权限中没有CREATE INDEX权限,因为以及包含在CREATE TABLE中;
· CREATE TABLE / PROCEDURE / CLUSTER权限中,以及包括了删除这些对象的权限;
· UNLIMITED TABLESPACE的系统权限是不能授予给某个角色的;

B. 对象权限
官方文档:Database Administration – Security Guide – Configuring Privilege and Role Authorization – Finding Information About User Privileges and Roles.
是指访问其他模式对象的权利
GRANT <obj_privilege> [(column_list)] [, <obj_privilege2> [(column_list)] …] | ALL [PRIVILEGES]
ON [schema.]<obj_name>
TO <user> | <role> | PUBLIC[, <user2> | <role2> … ]
[WITH ADMIN OPTIOIN];
-- 对象权限的转授,回收时可以被级联回收

REVOKE <sys_privilege>[, <sys_privilege2> … ]
FROM <user> | <role> | PUBLIC[, <user2> | <role2> … ];
SYS@Orcl> GRANT READ | WRITE | EXECUTE on DIRECTORY <dir_name> to <user>;

查看表级对象权限:
SELECT GRANTEE, TABLE_NAME, PRIVILEGE FROM user_tab_privs;
查看列级对象权限:
SELECT GRANTEE, TABLE_NAME, COLUMN_NAME PRIVILEGE FROM user_col_privs;

对象权限 表 视图 序列 过程PROCEDURE 调度程序SCHEDULER
ALTER Y Y Y Y
DEBUG Y Y
DELETE Y Y
EXECUTE Y Y
INDEX Y Y
INSERT Y Y
REFERENCES Y
SELECT Y Y Y
UPDATE Y Y
注释:
· 除此之外,视图还有MERGE VIEW和UNDER的对象权限;
· 不能在列级上授予表的SELECT对象权限,如果需要,要通过视图来实现。
C. 角色管理
由相关权限组成的命名组,用以授予用户或者角色。
非DBA用户如果要分配角色,就必须有GRANT ANY ROLE的系统权限或者拥有该角色的WITH ADMIN OPTION选项。
官方文档:Database Administration – Security Guide – Configuring Privilege and Role Authorization – Managing User Roles – Predefined Roles in an Oracle Database Installation.

查看角色权限:
SELECT * FROM role_sys_privs WHERE role = ‘’;
将角色授予用户:
SYS@Orcl> GRANT <role_name> to <u01> [WITH ADMIN OPTION];
使角色在当前会话失效:
set role none | <r01>[, <r02>];
SELECT * FROM SESSION_ROLES | SESSION_PRIVS;
a. 系统预定义角色 – 功能角色
官方文档:Database Administration – Security Guide – Configuring Privilege and Role Authorization – Finding Information About User Privileges and Roles.
 CONNECT
拥有权限:
CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE SYNONYM, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE, ALTER SESSION.
 RESOURCE
拥有权限:
CREATE CLUSTER, CREATE SEQUENCE, CREATE TRIGGER, CREATE TABLE, CREATE PROCEDURE, CREATE TYPE, CREATE OPERATOR, CREATE INDEXTYPE.

SELECT * FROM user_sys_privs; -- UNLIMITED TABLESPACE.
如果不想授予UNLIMITED TABLESPACE系统权限,应该:
SYS@Orcl> CREATE ROLE <r01>;
GRANT resource TO <r01>;
GRANT <r01> TO <u01>;
u01@Orcl> SELECT * FROM user_sys_privs;
 EXP_FULL_DATABASE
拥有权限:
READ ANY FILE GROUP, EXECUTE ANY PROCEDURE, RESUMABLE, SELECT ANY TABLE, EXECUTE ANY TYPE, CREATE SESSION, BACKUP ANY TABLE, ADMINISTER RESOURCE MANAGER, ADMINISTER SQL MANAGEMENT OBJECT, SELECT ANY SEQUENCE, CREATE TABLE.
b. 用户自定义角色
SYS@Orcl> CREATE ROLE <r01> [INDENTIFIED BY <passw>].

SELECT * FROM role_sys_privs; -- <r01>[, <r02>]
SELECT * FROM session_roles; -- null
set role <r01> INDENTIFIED BY <r01>[, <r02> INDENTIFIED BY <r02>];
SELECT * FROM session_roles; -- <r01>[, <r02>]
2. 概要文件
概要文件是口令限制和资源限制的命名集合。
非DBA用户如果要创建概要文件,就必须要有CREATE PROFILE的系统权限。
作用:限制用户执行过度消耗资源的SQL;自动断开空闲的会话;合理分配资源;控制用户口令的使用。

查看所有概要文件:
SELECT * FROM dba_profiles;
查看某用户的概要文件:
SELECT profile FROM dba_users WHERE username = ‘’;
创建概要文件:
CREATE PROFILE <p01> LIMIT <parameter> <value>;
应用概要文件:
ALTER USER <u01> PROFILE <p01>;
 口令策略参数
FAILED_LOGIN_ATTEMPS, PASSWORD_LOCK_TIME, PASSWORD_LIFE_TIME, PASSWORD_GRACE_TIME, PASSWORD_REUSE_TIME, PASSWORD_REUSE_MAX, PASSWORD_VERIFY_FUNCTION.
口令复杂度校验:
SYS@Orcl> @$ORACLE_HOME/rdbms/admin/utlpwdmg.sql
/* Function created.
Grant succeeded. -- GRANT EXECUTE on <verify_function_11G> to <PUBLIC>;
Profile altered. */
停止密码校验函数:
ALTER PROFILE <DEFAULT> LIMIT password_ verify_function null;
 资源限制参数
CPU时间、逻辑读、用户的并发会话数、空闲时间、连接时间、私有SGA区。
SYS@Orcl> ALTER SYSTEM set resource_limit = true; -- 必须要修改之后才能使用概要文件对资源进行限定。
CPU_PER_SESSION(单位:百分之一秒), SESSION_PER_USER, CONNECT_TIME, IDLE_TIME, LOGICAL_READS_PER_SESSION(内存), PRIVATE_SGA(单位:字节), CPU_PER_CALL, LOGICAL_READS_PER_CALL.
二十二、 导出导入与数据泵
1. 导出导入
导出、导入的作用:
重新组织表
在数据库、用户之间移动对象
升级数据库
实现逻辑的备份、恢复
(导出导入、闪回、数据泵都是逻辑备份工具;Rman、冷备份热备份才是物理备份工具)

导出导入3种方式:
· 交互式
[oracle@RedQueen ~]$ exp|imp
生成的dump文件会存放在当前目录。
· 命令行
格式:exp|imp <u01>/<passw> <KEYWORD1>=val <KEYWORD2>=(v1,v2[, … ])
-- 如果使用sys用户,需要对字符进行转义:exp \’sys\/oracle as sysdba\’ …
· 参数文件
[oracle@RedQueen ~]$ vi <file_name>
<KEYWORD1>=val
<KEYWORD2>=(v1,v2[, … ])
exp|imp parfile=<file_name>
A. Exp
查看帮助信息:
[oracle@RedQueen ~]$ exp help=y
 KEYWORD
KEYWORD DESC (DEFAULT VAL)
USERID <u01>/<passw>
或:USERID=\’/ as sysdba\’
LOG 指定位置生成日志
BUFFER
DIRECT 直接路径 (N)
FILE Output files (EXPDAT.DMP)
FILESIZE 每个dump文件最大的大小
PARFILE 把参数写在文件当中
FULL Exp full DB (N)
OWNER 进入导出用户模式
TRANSPORT_TABLESPACE 导出可传输表空间的元数据
TABLESPACES
TABLES
ROWS 导出行并显示行数(Y) / 导出表结构
QUERY 导出符合条件的记录。例如:
QUERY=\’WHERE <col>\=<val>\’
INDEXES (Y)
CONSTRAINTS (Y)
GRANTS 是否导出权限 (Y)
TRIGGERS (Y)
STATISTICS 分析对象大小
FLASHBACK_TIME
FLASHBACK_SCN
FEEDBACK 每导出x行显示进度 (0)
CONSISTENT 检查表中数据是否正在被修改 (N)
OBJECT_CONSISTENT 将导出的对象设置为只读 (N)
COMPRESS Import into 1 extent (Y)
TEMPLATE iAS模式(Internet Application Server)
注释:
CONSISTENT=y, 整个导出的内容在导出过程中没有被修改过,对系统资源会有更大的消耗,有可能会出现ORA-01550快照过旧的错误;OBJECT_CONSISTENT=y, 每个对象分别在导出过程中没有别修改过,也需要考虑系统资源的消耗情况。
B. Imp
 KEYWORD
KEYWORD DESC (DEFAULT VAL)
USERID <u01>/<passw>
LOG 屏幕显示日志
BUFFER
FILE Iutput files (EXPDAT.DMP)
FILESIZE 每个dump文件最大的大小
DATAFILES 指定数据文件的位置
PARFILE 把参数写在文件当中
FROMUSER
TOUSER
FULL Ixp full DB (N)
TRANSPORT_TABLESPACE 导入可传输表空间的元数据
TABLESPACES
TABLES
ROWS 导如行(Y) / 导入表结构
DATA_ONLY 仅仅导入数据
SHOW 只是列出文件内容 (N)
INDEXES (Y)
CONSTRAINTS (Y)
GRANTS 是否导入权限 (Y)
STATISTICS 分析对象大小
FEEDBACK 每导入x行显示进度 (0)
COMMIT 超过BUFFER参数大小之后就进行提交 (N)
IGNORE 忽略创建时的错误 (N)
INDEXFILE 将表 / 索引的信息写到一个指定的文件当中
SKIP_UNUSABLE_INDEXES 跳过不可用的索引 (N)
STREAMS_CONFIGURATION 导入流的一般元数据 (Y)
STREAMS_INSTANTIATION 导入流实例化元数据 (N)
注释:
· IGNORE=y, 如果表名重复,将不执行CREATE TABLE语句,而是直接插入数据(有可能会插入重复的数据),如果被插入的数据违反了约束(主键约束、唯一性约束等),那么出错的那些记录则不会被插入,导入过程中也会有警告;IGNORE=n, 如果表名重复,将不执行CREATE TABLE语句,也不会插入数据,而是忽略这个名字重复的表。
· COMMIT=y, 对大表进行导入操作应该使用COMMIT=y参数,对数据进行分批提交,由BUFFER参数来决定什么时候COMMIT。因为如果导入执行很长时间,那么一旦导入操作被中断,会导致回滚,占用回滚段以及很多时间(或者使用数据泵的方式进行导出导入更好);但是由于频繁地COMMIT,性能是会受到影响的。而且对于包含LONG、RAW、 DATE等类型的表,不论BUFFER设置多大,都是每插入一行进行提交。
· 导入多个dmp文件,可以写成file=<tbs01>.dmp,<tbs02>.dmp,<tbs03>.dmp,<tbs04>.dmp … 一定要写首个dmp文件,否则不能导入;不一定要写全,但要连续;如果不连续,则只能导入表的结构,不能导入表的数据。
C. 传输表空间
传输表空间的限制:字符集、字节存储序列、自包含
a. 字符集
查看字符集:
SELECT * FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET';

字符集不同报错:
导入表空间 –
[oracle@RedQueen ~]$ echo $ORACLE_SID
imp userid=\’/ as sysdba\’ tablespaces=<tbs01> file=/tmp/<tbs01>.dmp transport_tablespace=y datafiles=/tmp/<tbs01>.dbf fromuser=<u01> touser=<u01>
[ERROR] import done in US7ASCII character set and AL16UTF16 NCHAR character set
IMP-00017: …
ORA-29345: cannot plug a tablespace into a database using an imcompatible character set
ORA-06512: …
IMP-00000: Import terminated unsuccessfully
[Solution]
i. SHUTDOWN IMMEDIATE | NORMAL
ii. FULL Backup
iii. STARTUP MOUNT
iv. Alter:
ALTER SYSTEM enable restricted session;
ALTER SYSTEM set job_queue_processes = 0;
ALTER SYSTEM set aq_tm_processes = 0;
ALTER DATABASE open;
ALTER DATABASE character set <target_charset>;
[ERROR] ORA-12716: Cannot ALTER DATABASE CHARACTER SET when CLOB data exists.
[Solution] -- ignore…
ALTER DATABASE character set INTERNAL_USE <target_charset>;

[oracle@RedQueen ~]$ imp userid=\’/ as sysdba\’ tablespaces=<tbs01> file=/tmp/<tbs01>.dmp transport_tablespace=y datafiles=/tmp/<tbs01>.dbf fromuser=<u01> touser=<u01>
[ERROR] ORA-00721: changes by release <version1> cannot be used by <version2>
[Solution] 修改参数文件 / 升级

[oracle@RedQueen ~]$ imp userid=\’/ as sysdba\’ tablespaces=<tbs01> file=/tmp/<tbs01>.dmp transport_tablespace=y datafiles=/tmp/<tbs01>.dbf fromuser=<u01> touser=<u01>
SYS@prod> SELECT name FROM v$tablespace
b. 字节存储序列
字节存储序列决定了数据值在操作系统平台上的存储顺序,分为big endian和little endian。如果在不同的字节序平台之间进行传输表空间,需要首先进行转换:
/*先查看字节序,然后再转换*/
SYS@Orcl> SELECT db.platform_name, endian_format FROM v$transportable_platform tp, v$database db WHERE tp.platform_name=db.platform_name;
RMAN> convert tablespace test2 to platform ‘solaris[tm] OE (32-bit)’ format ‘d:/expdp_trans.dmp’;
[oracle@RedQueen ~]$ imp system/oracle file=expdp.dmp datafile=expdp_trans.dmp transport_tablespace=y
c. 自包含
查看表空间是否为自包含:
SYSTEM@Orcl> EXECUTE dbms_tts.transport_set_check(‘<tbs01>’, true);
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'DBMS_OUTPUT.ENABLE' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SYS@Orcl> conn / as sysdba
EXECUTE dbms_tts.transport_set_check(‘<tbs01>’, true);
SELECT * FROM transport_set_violations;
d. 传输表空间
传输表空间步骤:
 用户需要拥有CONNECT、RESOURCE权限才能进行传输表空间
SYS@Orcl> GRANT connect, resource TO <u01>;
 在进行传输表空间之前,需要对表空间置为只读
SYS@Orcl> ALTER TABLESPACE <tbs01> READ ONLY;
 导出表空间
[oracle@RedQueen ~]$ echo $ORACLE_SID
exp userid=\’/ as sysdba\’ tablespaces=<tbs01> file=<tbs01>.dmp transport_tablespace=y
ls /tmp/
 scp dmp文件和<tbs01>.dbf数据文件
 导入表空间
[oracle@RedQueen ~]$ echo $ORACLE_SID
imp userid=\’/ as sysdba\’ tablespaces=<tbs01> file=/tmp/<tbs01>.dmp transport_tablespace=y datafiles=/tmp/<tbs01>.dbf fromuser=<u01> touser=<u01>
2. 数据泵
格式:expdp|imp <u01>/<passw> DIRECTORY=dumpdir DUMPFILE= <scott>.dmp <KEYWORD1>=val <KEYWORD2>=(v1,v2[, … ])
A. Expdp
 KEYWORD
KEYWORD DESC
ATTACH Attach to an existing job.
CLUSTER [Y], 多为RAC环境下使用
COMPRESSION ALL, DATA_ONLY, [METADATA_ONLY], null
CONTENT [ALL], DATA_ONLY, METADATA_ONLY
类似于exp的rows参数
DATA_OPTIONS [XML_CLOBS], Data layer option flags.
DIRECTORY
DUMPFILE DUMPFILE=<dir>:<mydb_%U.dat>
类似于exp的file参数
ENCRYPTION ALL, DATA_ONLY, ENCRYPTED_COLUMNS_ONLY, NONE
ENCRYPTION_ALGORITHM [AES128], AES192, AES256
ENCRYPTION_MODE DUAL, PASSWORD, [TRANSPARENT]
ENCRYPTION_PASSWORD
ESTIMATE | ESTIMATE_ONLY [BLOCKS], STATISTICS, 分析
EXCLUDE EXCLUDE=SCHEMA:”=’HR’”
FILESIZE
FLASHBACK_SCN
FLASHBACK_TIME
FULL [N]
HELP [N]
INCLUDE INCLUDE=<obj_type>:<name_clause>, <obj_type2>:<\”LIKE\‘\%emp\%\’\”> /*对所有符号进行转义*/ | TABLE | TABLE_DATA …
JOB_NAME
LOGFILE
NETWORK_LINK Database link
NOLOGFILE [N]
PARALLEL
PARFILE
QUERY QUERY=employees:”WHERE dept_id > 10”
REMAP_DATA 需要指定转换函数
REMAP_DATA=EMP.EMPNO:<PACKAGE>.<FUNCTION>
REUSE_DUMPFILES [N], 覆盖如果存在的dump file
SAMPLE 导出百分之n的数据
SCHEMAS [<login schema>], 类似于exp的OWNER参数
SERVICE_NAME
SOURCE_EDITION
STATUS
TABLES TABLES=<HR.EMPLOYEES>, <SCHEMA.TAB>
TABLESPACES
TRANSPORTABLE ALWAYS, [NEVER]
TRANSPORT_FULL_CHECK [N]
TRANSPORT_TABLESPACES
VERSION [COMPATIBLE], LATEST

 交互式
KEYWORD DESC
ADD_FILE
CONTINUE_CLIENT Retrun to logging mode. Job will be restarted if idle.
EXIT_CLIENT Quit client session and leave job running.
FILESIZE
HELP
KILL_JOB
PARALLEL
REUSE_DUMPFILES [N]
START_JOB SKIP_CURRENT, start or resume current job.
STOP_JOB IMMEDIATE. Shutdown job execution and exits the client.
STATUS Frequency (secs) job status is to be mentioned.
Default [0] (secs) will show the status when available.

创建目录对象:
u01@Orcl> CREATE DIRECTORY <dir> as ‘<path>’;
ORA-01031: insufficient privileges
SYS@Orcl> GRANT CREATE ANY DIRECTORY to u01;
u01@Orcl> CREATE DIRECTORY <dir> as ‘<path>’;
查看目录对象:
SYS@Orcl> SELECT * FROM DBA_DIRECTORIES;
数据泵默认目录:
DIRECTORY_NAME DIRECTORY_PATH
DATA_PUMP_DIR $ORACLE_BASE/admin/<sid>/dpdump
授权:
SYS@Orcl> GRANT READ, WRITE ON DIRECTORY <dir> to <u01>;
查看数据泵帮助信息:
[Oracle@RedQueen ~]$ expdp help=y
B. Impdp
 KEYWORD
KEYWORD DESC
PARTITION_OPTIONS DEPARTITION, MERGE, [NONE]
REMAP_DATAFILE Redefine data file references in all DDL statements.
REMAP_SCHEMA REMAP_SCHEMA=<u01>:<u02>
类似于imp的FROMUSER和TOUSER参数
REMAP_TABLE REMAP_TABLE=<HR.EMPLOYEES>:<EMPS>
REMAP_TABLESPACE REMAP_TABLESPACE=<T1>:<T2>
REUSE_DATAFILES [N]
SKIP_UNUSABLE_INDEXES
SQLFILE Write all the SQL DDL to a specified file.
STATUS
STREAMS_CONFIGURATION Enable the loading of Streams metadata
TABLE_EXISTS_ACTION APPEND, REPLACE, [SKIP], TRUNCATE
TABLES
TABLESPACES
TRANSPORTABLE ALWAYS, [NEVER]
TRANSPORT_DATAFILES
TRANSPORT_FULL_CHECK [N]
TRANSPORT_TABLESPACES
VERSION [COMPATIBLE], LATEST

 交互式
KEYWORD DESC
CONTINUE_CLIENT Retrun to logging mode. Job will be restarted if idle.
EXIT_CLIENT Quit client session and leave job running.
HELP
KILL_JOB
PARALLEL
START_JOB SKIP_CURRENT, start or resume current job.
STOP_JOB IMMEDIATE. Shutdown job execution and exits the client.
STATUS Frequency (secs) job status is to be mentioned.
Default [0] (secs) will show the status when available.
C. 传输表空间
· 创建目录、授权
SYS@Orcl> CREATE DIRECTORY dir as ‘/home/oracle/’;
GRANT READ, WRITE on directory dir to u01;
GRANT EXP_FULL_DATABASE to u01;
· 将表空间设为只读
u01@Orcl> ALTER TABLESPACE <tbs01> READ ONLY;
· 传输表空间
ho scott/scott directory=dir dumpfile=<name>.dmp transportable=always …
· 将dump文件和数据文件.dbf发送到目标数据库站点
· impdp
ho impdp scott/scott directory=<dir> dumpfile=<name>.dmp transport_datafiles=’<path>/<datafile>.dbf’
二十三、 闪回
Oracle高可用技术:Real Application Cluster (RAC), Auto Storage Management (ASM), Flashback, Recovery Manager (RMan. 恢复时间比较长,可以使用DG实现秒级别的切换恢复), Data Guard (DG, 使用Golden Gate, Standby等)。

闪回是对数据进行逻辑恢复的技术,不能使用闪回对物理损坏(例如数据文件损坏)进行恢复。
闪回查询 闪回恢复
数据库级闪回 闪回数据库
表级闪回 闪回版本查询
闪回查询 闪回表
闪回删除
闪回数据归档
事务级闪回 闪回事务查询

闪回可以分为闪回查询、闪回恢复。闪回查询可以查询数据被DML的不同版本;闪回恢复将修改数据,闪回点之后的数据将全部丢失。
1. Flashback Version Query
闪回版本查询就是查询每次事务(某个时间段)所引起的数据行变化情况。主要作用:审计查询。
闪回版本查询使用的是undo表空间里记录的undo数据。当undo段的数据由于空间不足(因此需要保证undo表空间有充足的空闲空间、而且设置好guarantee选项)而被清除的时候,则无法闪回查询。
 语法:
SELECT <col>
FROM <schema.tab>
VERSIONS BETWEEN SCN <min_scn> AND <max_scn>
| VERSIONS BETWEEN TIMESTAMP to_timestamp(‘<start_ts>’, ‘<format>’) and to_timestamp(‘<end_ts>’, ‘<format>’)
WHERE <col_filter>
GROUP BY …
HAVING <group_filter>
ORDER BY …

· 不知道SCN、TIMESTAMP如何查询历史版本信息
SELECT versions_operation, versions_xid, versions_startscn, versions_endscn[, versions_starttime, versions_endtime], * FROM <tab> VERSIONS BETWEEN minvalue AND maxvalue; -- Delete操作和最后一次操作没有结束的SCN.
2. Flashback Transaction Query
闪回事务查询就是对(某个时间段)事务的查询和撤销。通过对事务的闪回分析,可以对数据库的表进行事务级的恢复。主要作用:事务恢复。
闪回事务查询也是使用undo表空间当中的undo数据。通过flashback_transaction_query视图的xid(可以首先使用闪回版本查询得到)和undo_sql,可以得到、执行事务的反转语句,就可以对事务进行闪回恢复。
使用闪回事务查询之前,必须启用重做日志流的其它日志记录,它是对撤销表空间中记录信息的增强补充。
SYS@Orcl> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
u01@Orcl> SELECT xid, undo_sql FROM flashback_transaction_query;
ORA-01031: insufficient privileges
-- 默认情况下只有SYS用户和DBA角色具有执行DBMS_FLASHBACK包的权限。
SYS@Orcl> GRANT EXECUTE on dbms_flashback to <u01>;
GRANT SELECT ANY TRANSATION to <u01>;
u01@Orcl> SELECT xid, undo_sql FROM flashback_transaction_query;

· ORA_ROWSCN
ORA_ROWSCN这个伪列是用来记录最后一次被修改的SCN的,默认是数据块级别,也就是这个数据块最后一次被修改的SCN。建表时可以使用rowdependencies关键字,使每行记录都有自己的ORA_ROWSCN。
CREATE TABLE <tab> (<col> <type>) ROWDEPENDENCIES;
3. Flashback Query
闪回查询是查询该表过去某个时间点的数据情况(主要作用),依赖于undo表空间的undo数据。
 语法
SELECT <col>
FROM <schema.tab>
AS OF SCN | TIMESTAMP -- 如果不知道SCN和TIMESTAMP, 可以用sysdate-n/1440.
WHERE <col_filter>
GROUP BY …
HAVING <group_filter>
ORDER BY …
· 将表恢复到过去某个时间点
CREATE TABLE <tab02> as SELECT * FROM <tab01> where 1=2;
SELECT * FROM <tab02>;
INSERT INTO <tab02> SELECT * FROM <tab01> AS OF SCN | TIMESTAMP;
COMMIT;
SELECT * FROM <tab02>;
4. Flashback Table
闪回表就是将表里的数据回退到某个时间点,使用的也是undo表空间中的undo数据。主要作用:闪回恢复。
可以往前闪回,也可以往后闪回。但SYS模式下的表不能使用闪回表技术(ORA-08185)。
 特性
在线操作
恢复到某个时间点或者SCN的数据
自动恢复相关属性,例如索引、触发器等
满足分布式的一致性
满足数据的一致性,所有相关对象自动一致
 局限性
不能对系统表(SYS用户)进行闪回操作
不能对DDL语句进行闪回操作(例如TRUNCATE等)
闪回操作会写入alert日志文件
闪回操作会产生undo和redo数据
 语法
FLASHBACK TABLE <schema.tab01>[, <schema.tab02>] TO SCN <scn> | TIMESTAMP <ts> | RESTORE POINT <restore_pt> [ENABLE | DISABLE TRIGGERS]
-- 要么同时成功,要么同时失败,多数用于有主外键关系的表。
-- 基于闪回点的闪回,需要先新建闪回点:CREATE RESTORE POINT <restore_pt>;

u01@Orcl> FLASHBACK TABLE <tab> to SCN <scn>;
ORA-08189: cannot flashback the table because row movement is not enabled
-- 必须启用行移动,才能使用闪回表。
ALTER TABLE <tab> ENABLE ROW MOVEMENT;
FLASHBACK TABLE <tab> to SCN <scn>;
5. Flashback Drop
闪回删除的主要作用是闪回恢复被drop的表,它使用的是回收站空间。
回收站是一个逻辑结构,不是物理数据结构。每个表空间都有一个叫做回收站的逻辑区域,当表空间不足的时候,就会覆盖回收站的空间。当删除表的时候,表的数据和存储的物理位置是没有变化的,只是将原表的名字改为回收站的对象名称。
闪回删除之后,该表的索引、触发器、授权、唯一约束、主键约束、非空约束会被恢复,但外键约束不可被恢复。
使用“DROP USER <u01> CASCADE”命令会绕过回收站,直接被清除掉。
 局限性
闪回删除对以下表不生效:
存放在SYSTEM表空间上的表
建立在字典管理方式的表空间上的表
删除时使用了PURGE选项
以下依赖对象不受保护:
位图索引
物化视图日志
外键一致性约束
 语法
u01@Orcl> FLASHBACK TABLE <tab> TO BEFORE DROP;

查询是否打开回收站功能
show parameter recyclebin
打开回收站功能
SYS@Orcl> ALTER SYSTEM SET recyclebin=on scope=spfile;
STARTUP FORCE
查看回收站中的对象名称
u01@Orcl> SELECT original_name, object_name FROM user_recyclebin;
使用回收站当中的对象名称可以查询数据
SELECT * FROM “<asdfjkl>”;
清空回收站
PURGE TABLE <tab | asdfjkl> | TABLESPACE <tbs> [USER <u01>] | RECYCLEBIN | DBA_RECYCLEBIN

· 先后删除同名的表,闪回删除的时候,会恢复最后一次被删除的表,恢复后另外一个表会因为同名而不能被恢复(ORA-38312: original name is used by an existing object)。
建议使用回收站中的对象名称(唯一);或者使用“u01@Orcl> FLASHBACK TABLE <tab01> TO BEFORE DROP RENAME TO <tab02>; ”。
6. Flashback Database
闪回数据库是一种快速、数据库的逻辑错误(包括TRUNCATE)恢复方案,这种恢复可以将数据库恢复到修改之前的某个时间点,只针对用户的逻辑错误进行恢复,不是涉及整个数据库的恢复,更有针对性,恢复时间大大减少。多数用于TRUNCATE、多表发生意外错误、删除了以用户等情况。
它使用闪回日志来恢复用户的逻辑错误。闪回日志由Oracle自动创建,保存在闪回恢复区当中。启用闪回数据库有两个前提条件:数据库开启归档模式、设置了闪回恢复区。可以使用“show parameter recover”来查看db_recovery_file_dest和db_recovery_file_dest_size两个参数。闪回日志的数据是由内存中的闪回缓冲区Flashback Buffer中变化的数据,按照一定时间间隔,通过RVWR进程,写入闪回日志Flashback Logs的。例如用户对表进行数据的增加或者删除,此时变化之前影像的操作会记录在闪回日志当中,一旦闪回,将利用相反的操作进行恢复。
使用闪回数据库,会使用resetlogs创建新的场景incarnation并打开数据库,闪回点之后的数据将丢失。
 局限性
不能解决物理错误
如果控制文件被重建、或者恢复,不能使用闪回数据库
不能恢复被删除的表空间
数据文件被压缩的时候,不能使用闪回数据库
 语法
FLASHBASE [STANDBY] DATABASE [<database_name>] TO [BEFORE] SCN <scn> | TIMESTAMP <ts> | RESTORE POINT <restore_pt>
 闪回数据库(利用导出导入,实现数据的不丢失)
SYS@Orcl> SHUTDOWN IMMDIATE
STARTUP MOUNT
SELECT to_char(sysdate, ‘yyyy-mon-dd hh24:mi:ss’) time FROM dual;
FLASHBACK DATABASE TO TIMESTAMP to_timestamp(‘<time>’, ‘yyyy-mon-dd hh24:mi:ss’);
ALTER DATABASE OPEN READ ONLY;
/*不是使用RESETLOGS选项,否则开启一个新的场景incarnation, 闪回点之后的数据就会被丢失了*/
[oracle@RedQueen ~]$ expdp system/oracle dumpfile=<dir>:<mydb_%U.dmp> schemas=<scott>
SYS@Orcl> SHUTDOWN IMMDIATE
STARTUP MOUNT
RECOVER DATABASE
ALTER DATABASE OPEN
[oracle@RedQueen ~]$ impdp system/oracle dumpfile=<dir>:<mydb.dmp> REMAP_SCHEMA=<scott>:<scott>

查询是否开启闪回数据库的功能
SELECT log_mode, flashback_on, open_mode FROM v$database;
开启闪回数据库的功能
SYS@Orcl> SHUTDOWN IMMEDIATE
STARTUP MOUNT
ALTER DATABASE FLASHBACK ON;
ORA-38706: Cannot turn on FLASHBACK DATABASE logging.
ORA-38707: Media recovery is not enabled. -- 没有开启归档模式
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE FLASHBACK ON;
ALTER DATABASE OPEN;
SELECT log_mode, flashback_on, open_mode FROM v$database;
[oracle@RedQueen ~]$ cd $ORACLE_BASE/fast_recovery_area/<SID>/flashback/
ll -tr -- 闪回日志
查看闪回缓冲区
SELECT * FROM v$sgastat WHERE name LIKE ‘%flashback%’;
7. Flashback Data Archive
闪回数据归档是将指定表变化的数据存储到闪回归档区当中。这些闪回归档区(一个或多个,每个闪回归档区可以有不同的保留策略)是一个逻辑概念,它创建在表空间当中,可以长期保存。
 限制
启用了闪回数据归档的表,不能使用DDL命令(11G R2可以truncate、add | drop column、alter table rename)。

配置闪回归档
CREATE FLASHBACK ARCHIVE [DEFAULT] <fb> TABLESPACE <tbs> QUOTA nM RETENTION <time -- 10 year>;
ALTER TABLE <tab> FLASHBACK ARCHIVE <fb>;
查看闪回归档区名称
SELECT flashback_archive_name FROM dba_flashback_archive;
查看表的闪回归档区信息
SELECT * FROM dba_flashback_archive_tables;
增加闪回归档空间
ALTER FLASHBACK ARCHIVE <fb> ADD TABLESPACE <tbs> QUOTA [nM];
修改保留时间
ALTER FLASHBACK ARCHIVE <fb> MODIFY RETENTION 5 year;
对某个表禁用闪回数据归档
ALTER TABLE <tab> NO FLASHBACK ARCHIVE;
删除闪回归档区
DROP FLASHBACK ARCHIVE <fb>;
二十四、 备份与RMAN
备份恢复的工具大致有RMAN、操作系统命令、SQL*Plus等等。
1. 概念
物理备份
简单地复制备份数据文件、控制文件、归档日志等数据库文件。包括冷备份、热备份;
逻辑备份
用导入导出、数据泵等工具来实现数据的备份。
脱机备份
关闭数据库进行备份,又称冷备份、一致性备份;
联机备份
在数据库开启的时候进行备份,又称热备份、非一致性备份。
全部备份
包含所有数据文件、至少一个控制文件、参数文件、密码文件等。
完整备份
一个或多个数据文件的完整副本;
增量备份
包含从上一次备份以来,被修改或者添加的数据块。
具体分为差异增量备份、累计增量备份:
差异增量备份(默认)
备份上级、同级备份以来,所有变化的数据块;
累计增量备份
备份上级备份以来,所有变化的数据块。
· 0级增量备份:所有增量备份的基础,完整备份,包含所有used数据块;
RMAN> backup incremental level 0 database;
· 全库备份:包含所有数据块(used、unused),但不能作为1级备份的基础
RMAN> backup database;
· 1级差异增量备份:包含最近一次1级差异或者累计备份以来,修改过的数据块
RMAN> backup incremental level 1 database;
· 1级累计增量备份:只包含最近一次0级增量备份以来,修改过的数据块
RMAN> backup incremental level 1 cumulative database;
影像副本
相当于使用cp命令进行的备份;
备份集
使用RMAN生成的备份片piece(物理文件)所组成的逻辑结构。
还原
将备份文件拷贝回原来的位置;
恢复
在还原的基础上,使用联机重做日志和归档日志,将数据库刷新到最新的SCN。

· 备份策略
多路复用控制文件
多路复用联机重做日志文件
将数据库置于归档模式下,并将重做日志归档存放到多个位置
经常(定期)备份数据库文件,尽可能创建多个副本到可靠位置
· 备份的主要对象
数据文件
联机重做日志文件
控制文件
undo撤销文件
可选的备份文件(参数文件、密码文件等)
· 常见备份类型
联机数据库备份
脱机数据库备份
整个数据库
表空间
数据文件
控制文件
日志文件
参数文件

· 恢复的类型
恢复的类型分为实例恢复、崩溃恢复、介质恢复。介质恢复具体分为完全恢复和不完全恢复。
其中完全恢复是指,使用联机重做日志、归档日志,与数据库、表空间、数据文件等的备份结合使用,使数据库刷新恢复到最新的时间点(也就是没有丢失数据);不完全恢复则是将数据库恢复到过去的某个时间点(也就是一般会丢失数据)。
2. 冷备份
在数据库关闭的情况下进行的备份(脱机备份)。

冷备份过程
SYS@Orcl> SELECT name FROM v$datafile; -- 查看数据文件
SELECT name FROM v$tempfile; -- 查看临时文件
SELECT member FROM v$logfile; -- 查看日志文件
SELECT name FROM v$controlfile; 查看控制文件
SHUTDOWN IMMEDIATE
[oracle@RedQueen ~]$ cd $ORACLE_BASE/oradata/<sid>/
cp * </dir>
 缺点
数据库必须处于一致性关闭状态、不能实现基于表、用户级别的数据恢复。通常用于重建数据库。

不完全恢复(没有开启归档模式)
(SYS@Orcl> RECOVER DATABASE UNTIL CANCEL | TIME | CHANGE)
SYS@Orcl> STARTUP FORCE
ORA-01157: cannot identify/lock data file n – see DBWR trace file
ORA-01110: data file n: ‘$ORACLE_BASE/oradata/<sid>/<datafile>.dbf’
[oracle@RedQueen ~]$ cp <path>/<bcp>.dbf $ORACLE_BASE/oradata/<sid>/
ls -- 还原
SYS@Orcl> RECOVER DATABASE | DATAFILE n;
ORA-00279: change n generated at …
ORA-00289: suggestion: <$ORACLE_BASE/fast_recovery_area/<SID>/archivelog/ … >
ORA-00280: change n for thread m is in sequence #o
/*如果开启了归档模式,会直接显示“Media recovery complete”。
可以查看警告文件:$ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace/.trc
Media Recovery Start
Recovery of Online Redo Log: …
Media Recovery Complete (sid)
Completed: ALTER DATABASE RECOVER database */
ARCHIVE LOG LIST;
-- Database log mode, Oldest online log sequence, Current log sequence.
RECOVER DATABASE UNTIL CANCEL;
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
CANCEL
ORA-01547, ORA-01194, ORA-01110,
ORA-01112: media recovery not started
ALTER DATABASE OPEN;
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
ALTER DATABASE OPEN RESETLOGS;
ORA-01194: file n needs more recovery to be consistent
ORA-01110: data file n: ‘<$ORACLE_BASE/oradata/<sid>/<name>.dbf>’
ALTER SYSTEM SET “_allow_resetlogs_corruption”=true SCOPE=spfile;
STARTUP FORCE
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
SELECT status FROM v$instance; -- MOUNTED.
ALTER DATABASE OPEN RESETLOGS;
ORA-00600: interal error code, arguments: …
ORA-01092: ORACLE instance terminated. Disconnection forced
Process ID: …
Session ID: … Serial number: …
exit
sqlplus / as sysdba
Connected to an idle instance.
STARTUP -- OK.
ALTER SYSTEM RESET “_allow_resetlogs_corruption” SCOPE=spfile;
STARTUP FORCE
3. 热备份
在数据库处于open状态下,对数据文件、控制文件、重做日志文件、参数文件、密码文件等等进行的备份。
在热备份过程中,数据文件头部的SCN会被锁定(冻结),不会有任何数据写入数据文件。但此时数据库仍然会支持DML操作,因为它会把变化的数据写入重做日志文件;当数据文件 / 表空间结束备份模式之后(物理拷贝完成后),会触发恢复过程(解冻;由Oracle自动完成),从而使数据文件、控制文件、重做日志文件当中记录的SCN号保持一致。
 热备份命令
SYS@Orcl> SELECT name FROM v$datafile; -- 查看数据文件
SELECT name FROM v$tempfile; -- 查看临时文件
SELECT member FROM v$logfile; -- 查看日志文件
SELECT name FROM v$controlfile; 查看控制文件
ALTER DATABASE | TABLESPACE <tbs01> BEGIN BACKUP; -- 备份数据库 / 表空间
ALTER DATABASE BACKUP CONTROLFILE to ‘<dir>’ [REUSE] | to TRACE as ‘<dir>’;
-- 备份控制文件
CREATE PFILE[=’<dir>’] FROM SPFILE; -- 备份参数文件
/*临时表空间不需要进行备份,否则会报错。
如果临时表空间出现故障,只需重新创建一个新的就可以了:
“CREATE TEMPORARY TABLESPACE <temp01> tempfile ‘<path>/<tmp>.dbf’ SIZE nM; ”*/
[oracle@RedQueen ~]$ cd $ORACLE_BASE/oradata/<sid>/
cp * </dir>
SYS@Orcl> ALTER DATABASE | TABLESPACE <tbs01> END BACKUP;

 热备份是前提是:数据库处于归档模式。
SYS@Orcl> SELECT tablespace_name, file_name FROM dba_data_files;
-- 查看表空间所在的数据文件
ALTER TABLESPACE <tbs01> BEGIN BACKUP;
ORA-01123: cannot start online backup; media recovery not enabled
ARCHIVE LOG LIST -- No Archive Mode
SHUTDOWN IMMEDIATE
STARTUP MOUNT
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
ARCHIVE LOG LIST; -- Archive Mode
ALTER TABLESPACE <tbs01> BEGIN BACKUP;
[oracle@RedQueen ~]$ cd $ORACLE_BASE/oradata/<sid>/
cp <tbs01.dbf> </dir>
SYS@Orcl> ALTER TABLESPACE <tbs01> END BACKUP;

 数据库热备份过程中,被强制重启
SYS@Orcl> ALTER TABLESPACE <tbs01> BEGIN BACKUP;
STARTUP FORCE -- 模拟特殊情况,被强制重启
ORA-10873: file n needs to be either taken out of backup mode or media recovered
ORA-01110: data file n: ‘<dir>/<name>.dbf’
[oracle@RedQueen ~]$ vi $ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace.trc
SYS@Orcl> SELECT * FROM v$backup; -- ACTIVE: backup mode.
ALTER DATABASE DATAFILE n END BACKUP | RECOVER DATAFILE n;
SELECT * FROM v$backup;
ALTER DATABASE OPEN;

 undo表空间所对应的数据文件丢失
u01@Orcl> CREATE TABLE <tab>( … );
ORA-00604: error occurred at recursive SQL level n
ORA-01116: error in opening database file n
ORA-01110: data file n: ‘<$ORACLE_BASE/oradata/<sid>/undotbs.dbf>’
ORA-27041: unable to open file
Linux-x86_64 Error: No such a file or directory
RECOVER DATABASE | DATAFILE n;

 非系统表空间,在没有备份的情况下,进行完全恢复(已经开启了归档模式)
SYS@Orcl> SELECT tablespace_name, file_name FROM dba_data_files;
-- 查看表空间所在的数据文件
STARTUP FORCE
ORA-01157: cannot identify/lock data file n – see DBWR trace file
ORA-01110: data file n: ‘$ORACLE_HOME/dbs/<datafile>.dbf’
SELECT status FROM v$instance; -- MOUNTED.
SELECT * FROM v$recover_file; -- ONLINE; FILE NOT FOUND.
ALTER DATABASE DATAFILE n OFFLINE;
ALTER DATABASE OPEN;
/*因为没有备份,所以不能还原(Restore)。但由于控制文件当中记录了表空间的信息,所以我们只需要先创建一个原来的数据文件,然后再来回复即可。*/
ALTER DATABASE CREATE DATAFILE ‘[<path>/]<name>.dbf’;
RECOVER DATAFILE n;
ALTER DATABASE DATAFILE n ONLINE;

 数据库结构被修改过之后,丢失所有控制文件
SYS@Orcl> STARTUP FORCE
ORA-00205: error in identifying control file, check alert log for more info
[oracle@RedQueen ~]$ less $ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace/alert_<sid>.log
ORA-00210: cannot open the specified control file
ORA-00202: control file: ‘$ORACLE_BASE/oradata/<sid>/<control01>.ctl’ | ‘$ORACLE_BASE/fast_recovery_area/<sid>/<control02>.ctl’
Linux-x86_64 Error: No such file or directory
SYS@Orcl> SELECT name FROM v$controlfile;
ho cp <path>/<bcp>.ctl <dir>/<control01>.ctl
ho cp <path>/<bcp>.ctl <dir>/<control02>.ctl
ALTER DATABASE MOUNT;
ALTER DATABASE OPEN;
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
ALTER DATABASE OPEN RESETLOGS;
ORA-01194: file n needs more recovery to be consistent -- 控制文件版本不够新
ORA-01110: data file: ‘<$ORACLE_BASE/oradata/<sid>/ … >’
RECOVER DATABASE;
ORA-00283: recovery session canceled due to errors
ORA-01610: recovery using the BACKUP CONTROLFILE option must be done
RECOVER DATABASE USING BACKUP CONTROLFILE;
ORA-00279: change n generated at …
ORA-00289: suggestion: <$ORACLE_BASE/fast_recovery_area/<SID>/archivelog/ … >
ORA-00280: change n for thread m is in sequence #o
Specify log: {<RET> = suggested | filename | AUTO | CANCEL}
SYS@Orcl> ARCHIVE LOG LIST | SELECT group#, status FROM v$log; -- SessionB查看当前日志o
$ORACLE_BASE/oradata/<sid>/<redo04>.log
ORA-00283: recovery session canceled due to errors
ORA-01244: unnamed datafile(s) added to control file by media recovery
ORA-01110: data file n: ‘<$ORACLE_HOME>/ … ’ -- 控制文件之后,数据结构被修改过
ORA-01112: media recovery not started
SELECT name FROM v$datafile;
-- 会发现系统自动定义的数据文件名称(例如UNNAMED00006,可能没有.dbf)
ALTER DATABASE CREATE DATAFILE ‘<path>/<UNNAMED00006>’ AS ‘<$ORACLE_HOME>/ …’;
SELECT name FROM v$datafile;
RECOVER DATABASE USING BACKUP CONTROLFILE;
ORA-00279: change n generated at …
ORA-00289: suggestion: <$ORACLE_BASE/fast_recovery_area/<SID>/archivelog/ … >
ORA-00280: change n for thread m is in sequence #o
Specify log: {<RET> = suggested | filename | AUTO | CANCEL}
$ORACLE_BASE/oradata/<sid>/<redo04>.log
Media recovery complete.
ALTER DATABASE OPEN;
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
ALTER DATABASE OPEN RESETLOGS;
4. RMAN
特别地,RMAN(Recovery Manager)支持对增量数据进行块级别的备份和介质恢复,支持镜像副本和备份集,也可以实现建立副本数据库。备份集只包含使用过的数据块,而镜像副本则包含了没有使用过的数据块。
RMAN其实是一个可执行程序,放在$ORACLE_HOME/bin/目录下面。
A. 目标数据库与恢复目录
默认的情况下,RMAN在备份、还原、恢复的时候,会产生一些元数据信息,这些元数据信息会保存在目标数据库的控制文件当中(此时控制文件就是存储仓库了);而备份的目的地,默认是闪回恢复区$ORACLE_BASE/flash_recovery_area/<SID>/backupset/<os_date>
a. 目标数据库
当不使用catalog的时候,RMAN备份、还原、恢复的元数据信息是存放在控制文件的可变部分的,由参数control_file_record_keep_time控制保存时间,有可能会被覆盖。所有Oracle建议:
启动控制文件自动备份的功能;
把DBID记录下来;
将控制文件冗余到不同的磁盘上;
保留完整的RMAN备份日志。
b. 恢复目录
即使选择恢复目录的方式,也需要对恢复目录进行备份。不过一般不需要用RMAN,只需要EXP就可以了。
Catalog的优点:
能保留更多的历史备份信息;
一个恢复目录能管理、备份多个目标数据库。
使用catalog之前,需要把目标数据库的DBID等信息注册到恢复目录中,RMAN以DBID来识别数据库。
[oracle@RedQueen ~]$ export ORACLE_SID=<catalog>
echo $ORACLE_SID
sqlplus <sys>/<oracle>@<catalog> as sysdba
SYS@catalog> CREATE TABLESPACE <catalog> DATAFILE ‘$ORACLE_BASE/oradata/<sid>/<catalog01>.dbf’ SIZE 8G EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
CREATE USER <cat> identified by <cat> DEFAULT TABLESPACE <catalog> [quota unlimted on <catalog>];
GRANT connect, resource, recovery_catalog_owner TO <cat>;
[oracle@RedQueen ~]$ rman catalog <cat>/<cat>@<catalog>
RMAN> create catalog tablespace <catalog>;
exit;
[oracle@RedQueen ~]$ rman target system/oracle@orcl catalog <cat>/<cat>@<catalog>
connected to target database: ORCL (DBID= … )
connected to recovery catalog database
RMAN> register database;
 概念
目标数据库
需要完成备份、还原、恢复的数据库
服务器通道
完成复制工作的服务器进程
存储仓库
存储了目标数据库与备份相关的元数据,包括有:目标数据库物理结构的详细信息、数据文件的位置、备份的细节、RMAN的配置信息等等。
恢复目录
实际上就是另外一个数据库的表空间

 语法
不连接数据库,仅启动RMAN
[oracle@RedQueen ~]$ rman
连接数据库
[oracle@RedQueen ~]$ echo $ORACLE_SID
| SYS@Orcl> SELECT dbid FROM v$database;
RMAN> connect target /
connected to target database: <SID> (DBID= … )
启动RMAN并连接到数据库
[oracle@RedQueen ~]$ rman target /
connected to target database: <SID> (DBID= … )
启动RMAN并同时连接到目标数据库、恢复目录
[oracle@RedQueen ~]$ rman target <u01>/<passw01>/<orcl> catalog <u02>/<passw02>@<prod>

B. 备份
RMAN> backup[ as copy] database | datafile n, m | tablespace <tbs01> | current controlfile | spfile | archivelog all[ format ‘<path01>[/%U]’[, format ‘<path02>[/%U]’] ];
/* 1. 备份过程当中会校验数据块
2. as copy选项的备份路径:$ORACLE_BASE/fast_recovery_area/<SID>/datafile/
3. RMAN是不会对redo日志文件进行备份的。如果需要,就先“ALTER SYSTEM ARCHIVE LOG CURRENT; ”,然后使用上面的backup archivelog all进行备份。*/
检查备份片
RMAN> crosscheck backup [of database | tablespace <tbs01> | datafile n, m … | controlfile | spfile];
/* list backup [summary] | list copy命令显示的信息(备份片状态)可能不是最新的,需要使用crosscheck backup进行更新。
EXPIRED: 失效;OBSOLETE: 过期*/
查询过期的备份片
RMAN> report obsolete;
备份镜像副本
RMAN> copy datafile n to ‘<path>/<name>.dbf’ | backup as copy datafile n;
删除过期的备份片
RMAN> delete obsolete;
report obsolete;
删除失效的备份片
RMAN> delete expired backup;
crosscheck backup;
删除备份片
RMAN> delete backup;
删除镜像副本
RMAN> delete copy;

可以使用Run块的方式进行备份:
RMAN> Run {
allocate channel <ch01> type disk -- 分配通道
maxpiecesize = nG; -- 最大备份片为nG
backup as compressed backup set format ‘<path>/<%U>’ filesperset n database;
-- filesperset, 每个备份集中最多包含多少个数据文件,结合通道数来考虑、确定n.
release channel <ch01>;
}

全局 / 本地备份脚本
[oracle@RedQueen ~]$ rman target system/oracle@orcl catalog <cat>/<cat>@<catalog>
RMAN> create [global] script global_full_backup
comment ‘ … ’
{
backup database plus archivelog tag=’’;
delete obsolete [recovery window of n days];
}
查看脚本内容
RMAN> print script <script>;
查看当前恢复目录内的脚本
list [global | all] script <script>;
更新脚本
RMAN> replace [global] script <script>
{

}
删除脚本
RMAN> delete [global] script <script>;
执行脚本
[oracle@RedQueen ~]$ rman target system/oracle@orcl catalog <cat>/<cat>@catalog script ‘<script>’
| RMAN> run {
execute [global] script <script>;
}
· 可以嵌套执行脚本
C. 恢复
恢复数据库 / 表空间 / 重做日志
RMAN> restore | recover database | tablespace <tbs01> | archivelog all;
恢复控制文件 / 参数文件
RMAN> restore controlfile | spfile to ‘<path>/ …’ from autobackup;
recover controlfile;
块级别的恢复
RMAN> blockrecover datafile n, block m;
还原检查、恢复测试
RMAN> validate database | backupset n;
| restore database validate;
将数据文件还原到新的路径
SYS@Orcl> SELECT file#, name FROM v$datafile; -- 查看数据文件编号
RMAN> Run {
set newname for datafile n to ‘<new_dir>/<sys>.dbf’;
restore database | datafile n | tablespace <tbs01>;
switch datafile all | n; -- 更新控制文件
recover database | datafile n | tablespace <tbs01>;
alter database open;
}
恢复参数文件
RMAN> startup nomount force;
SYS@Orcl> SELECT dbid FROM v$database;
ORA-01507: database not mounted
RMAN> list backup of spfile -- 查看路径,文件名里有DBID.
set dbid= …
restore spfile from ‘ … ’;
shutdown immediate
[oracle@RedQueen ~]$ cd $ORACLE_HOME/dbs/
ls
RMAN> startup
破坏某个数据块
[root@RedQueen ~]$ dd of=$ORACLE_BASE/oradata/orcl/block.dbf bs=8192 conv=notrunc seek=20
查看数据块坏块
SYS@Orcl> SELECT * FROM v$database_block_corruption;
不完全恢复
RMAN> restore database until scn n | “to_date(‘<time>’, ‘yyyy-mm-dd hh24:mi:ss’)” | sequence m thread o; -- sequence = m, 但不包含m。
recover database;
alter database open resetlogs ;
从指定Tag中恢复
RMAN> restore from tag = ‘ … ’;

 数据文件、控制文件、参数文件丢失,还原并恢复数据库
RMAN> startup mount force
list backup -- 获取备份片的路径、数据文件编号、日志序列号
恢复参数文件
SYS@Orcl> DECLARE
devtype VARCHAR2(256);
done BOOLEAN;
BEGIN
devtype:=dbms_backup_restore.deviceallocate(NULL);
sys.dbms_backup_restore.restoresetdatafile;
sys.dbms_backup_restore.restorespfileto(‘$ORACLE_HOME/dbs/init<sid>.ora’);
sys.dbms_backup_restore.restorebackuppiece(‘$ORACLE_BASE/fast_recovery_area/<SID>/backupset/ … ’, done=>done);
sys.dbms_backup_restore.devicedeallocate(NULL);
END;
/
[oracle@RedQueen ~]$ cd $ORACLE_HOME/dbs/
ls
RMAN> shutdown immediate
Startup
恢复控制文件
SYS@Orcl> SELECT name FROM v$controlfile; -- 获取控制文件位置
DECLARE
devtype VARCHAR2(256);
done BOOLEAN;
BEGIN
devtype:=dbms_backup_restore.deviceallocate(NULL);
sys.dbms_backup_restore.restoresetdatafile;
sys.dbms_backup_restore.restorecontrolfileto(‘$ORACLE_BASE/oradata/<sid>/<control01>.ctl’);
sys.dbms_backup_restore.restorebackuppiece(‘$ORACLE_BASE/fast_recovery_area/<SID>/backupset/ … ’, done=>done); -- 确保备份片是正确的
sys.dbms_backup_restore.devicedeallocate(NULL);
END;
/
ho cp $ORACLE_BASE/oradata/<sid>/<control01>.ctl $ORACLE_BASE/fast_recovery_area/<sid>/<control02>.ctl
ALTER DATABASE MOUNT;
恢复数据文件
DECLARE
devtype VARCHAR2(256);
done BOOLEAN;
BEGIN
devtype:=dbms_backup_restore.deviceallocate(type=>’’, ident=>’t1’);
sys.dbms_backup_restore.restoresetdatafile;
sys.dbms_backup_restore.restoredatafileto(dfnumber=>01, to_name=>‘$ORACLE_BASE/oradata/<sid>/<system01>.dbf’);

sys.dbms_backup_restore.restorebackuppiece(‘$ORACLE_BASE/fast_recovery_area/<SID>/backupset/ … ’, done=>done); -- 确保备份片是正确的
sys.dbms_backup_restore.devicedeallocate;
END;
/
[oracle@RedQueen ~]$ cd $ORACLE_BASE/oradata/<sid>/
ls
恢复归档文件
DECLARE
devtype VARCHAR2(256);
done BOOLEAN;
BEGIN
devtype:=sys.dbms_backup_restore.deviceallocate(type=>’’, ident=>’t1’);
sys.dbms_backup_restore.restoresetarchivedlog(destination=>’$ORACLE_BASE/fast_recovery_area/<SID>/archivelog/ … ’);
sys.dbms_backup_restore.restorearchivedlogto(thread=>1, sequence=>n);
sys.dbms_backup_restore.restorebackuppiece(done=>done, handle=>‘$ORACLE_BASE/fast_recovery_area/<SID>/backupset/ … ’, params=>null); -- 确保备份片是正确的
sys.dbms_backup_restore.devicedeallocate;
END;
/
ALTER DATABASE OPEN;
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
ALTER DATABASE OPEN RESETLOGS;
ORA-01152: file n was not restored from a sufficiently old backup
ORA-01110: datafile: ‘<$ORACLE_BASE/oradata/<sid>/ … >’
RECOVER DATABASE;
ORA-00283: recovery session canceled due to errors
ORA-01610: recovery using the BACKUP CONTROLFILE option must be done
RECOVER DATABASE USING BACKUP CONTROLFILE;
ORA-00279: …
ORA-00298: suggestion: <path>/archive.arc
ORA-00280: … sequence #n
Specify log: {<RET> = suggested | filename | AUTO | CANCEL}
SYS@Orcl> ARCHIVE LOG LIST; -- Session B, 获取当前日志文件
SELECT group#, status FROM v$log;
SYS@Orcl> $ORACLE_BASE/oradata/<sid>/<redo04>.log
Log applied.
Media recovery complete.
ALTER DATABASE OPEN;
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
ALTER DATABASE OPEN RESETLOGS;
ARCHIVE LOG LIST;

 DRA(Data Recovery Advisor)
/*前提是必须要有备份。而且,不算很好用。*/
列出故障
RMAN> validate database;
/*有时候会列不出故障,需要先“validate database; ”进行校验检查。*/
list failure;
修复故障的建议
RMAN> advise failure; -- 会生成一个脚本,可以查看一下。
[oracle@RedQueen ~]$ less $ORACLE_BASE/diag/rdbms/<sid>/<sid>/hm …
修复故障
RMAN> repair failure;
数据文件丢失,恢复数据库
shutdown immediate
startup mount
restore database;
recover database;
恢复完之后,检查数据库
RMAN> validate database;

 RMAN提示符下执行SQL、PL/SQL语句
RMAN> SQL ‘SELECT * FROM <tab>’;
using target database control file instead of recovery catalog
sql statement: SELECT * FROM <tab>
-- 建议不要使用查询语句,因为不会有结果输出;
SQL “CREATE TABLESPACE <tbs01> DATAFILE ’’<datafile>.dbf’’ SIZE nM”;
-- 如果<cmd>中含有单引号,应该使用双引号,两个单引号的格式;
STARTUP … | SHUTDOWN … | ALTER DATABASE … | ALTER SYSTEM …
-- 这些命令可以直接执行,不需要加“ SQL’ … ’ ”;
RUN {
sql ‘ … ’;
}
-- 也可以使用Run块的方式执行,要么全部执行成功,要么全部失败。

 进入OS命令行
RMAN> host;
[oracle@RedQueen ~]$ exit
host command complete
RMAN>

 list 命令
列出详细备份信息
RMAN> list backup
列出过期备份的信息
list expired backup
列出主要备份信息
list backup summary
列出各种文件类型的详细备份信息
list backup by file
列出各种文件类型的主要备份信息
list backup [of database | archivelog | tablespace <tbs01> | datafile n, m … ] summary
/*其中TY: B表示backup, A表示Archivelog
LV: F表示full backup, 0, 1, 2, 3… 表示incremental level (增量)备份
S: A表示Available, X表示expired. */
列出副本镜像(备份)信息
list copy | backup [of database | controlfile | tablespace <tbs01> | datafile n, m … | archivelog all | archivelog from SCN <scn> | spfile]
列出数据库逻辑生存期
list incarnation;

 查看表空间、数据文件大小等信息
RMAN> report schema

 查看RMAN所有的配置信息
RMAN> show all;
配置RMAN
RMAN> CONFIGURE …
RETENTION POLICY TO REDUNDANCY n 保留n份相同的备份
RETENTION POLICY TO RECOVERY WINDOW OF n DAYS 保留n天之内的备份
BACKUP OPTIMIZATION ON
DEFAULT DEVICE TYPE TO DISK | SBT 备份到磁盘 / 磁带
CONTROLFILE AUTOBACKUP ON 当备份数据文件时,自动备份控制文件、参数文件,默认备份到:
$ORACLE_BASE/fast_recovery_area/<SID>/autobackup/
CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO ‘[<path>/]%F’ 自动备份文件的格式、路径
DEVICE TYPE DISK PARALLELISM n BACKUP TYPE TO[COMPRESSED] BACKUPSET | COPY
ENCRYPTION ALGORITHM ‘AES256’ | CLEAR 可以查看v$rman_encryption_algorithms视图
设置完之后可以使用“show encryption algorithm”进行查看
CHANNEL n DEVICE TYPE DISK FORMAT ‘<path>/<bcp>%U’ 设置通道的保存路径
注释:FORMAT字符串替代变量
%u 每个备份集生成一个唯一的名称
%p 表示备份片在该备份集中的编号
%c 备份片的拷贝数
%U %u_%p_%c, 最常用的命名方式
%F c-<DBID>-YYYYMMDD-QQ, QQ是1-256的序列
%d 数据库名称

 设置加密的备份片
RMAN> configure encryption for database on;
set encryption on identified by “<passw>”only;
backup datafile n;
shutdown immediate
startup mount
set encryption identified by “<passw>”;
restore datafile n;
recover datafile n;
alter database open;
二十五、 ASM
官方文档:Database Administration – Administrator’s Guide –Using Oracle Managed Files.
自动存储管理Auto Storage Management(ASM), 采用OMF文件格式来创建目录和文件(原理类似于Linux的逻辑卷LVM),可以实现条带化、镜像数据文件(可以设置镜像方式,例如外部冗余、常规冗余、高冗余)、恢复文件(例如某个磁盘坏了,当把新的可用的磁盘添加进来的时候,ASM会自动平衡,达到恢复文件的效果)。而所谓就是将一块连续的数据分成若干个小部分,将他们分散存储到不同的磁盘上去,效果是能够自动地将I/O均衡到多个物理磁盘上。这就使得多个进程能够同时访问数据的多个不同部分,而不会造成磁盘冲突,从而最大程度地获得I/O并行能力,提高性能。
文件按照分配单元Allocation Units(AUs)平衡分布在ASM磁盘组的所有磁盘当中,并用索引来跟踪每个AUs的位置。ASM支持动态的增加、减少磁盘,而此时AUs会自动重新均衡磁盘分布。
ASM磁盘组中有多个磁盘,当我们存储数据文件时,ASM会自动把数据库文件进行条带化分割,将文件平衡地存储在多个磁盘上,均衡了磁盘的存储。
ASM的优点:自动的磁盘管理、文件级别的镜像、避免磁盘热点(均衡I/O)、方便管理数据文件、部署简单。
 使用ASM的时候,只需要设置以下3个参数(ALTER SYSTEM SET … ):
DB_CREATE_FILE_DEST
默认为空。给Datafiles, Tempfiles, Redo log files, Control files, Block change tracking files使用。
创建完表空间之后,可以使用“SELECT name FROM v$datafile; ”进行查看:<path>/<SID>/datafile/ …
DB_CREATE_ONLINE_LOG_DEST_n
给Redo log files, Control files使用。
DB_RECOVERY_FILE_DEST
闪回恢复区。给(multiplexed copies of)Redo log files, (multiplexed copies of)Control files, RMAN backups, Archived logs, Flashback logs使用.
1. ASM体系结构
使用ASM需要创建一个ASM实例,用于管理ASM磁盘组,但ASM实例并不代替RDBMS实例来读写数据文件,数据是直接在ASM磁盘和RDBMS实例之间进行传递的,ASM实例仅用来定位数据文件。使用的时候,需要先打开ASM实例,再打开RDBMS实例。
ASM实例拥有和普通的RDBMS实例类似的内存结构和后台进程,除此之外还添加了两个后台进程:RBAL和ARBn。RBAL用于管理磁盘组之间的动态平衡,ARBn用于完成AUs的移动。
ASM磁盘组是一组磁盘 / 磁盘分区的逻辑组合,用户只需要关心磁盘组层面,其它的交由ASM去完成。
一个ASM文件会在该磁盘组的多个磁盘上均匀分布(如果磁盘一个大,一个小,那么会按比例分布,但建议磁盘大小差不多),此外,磁盘再平衡也是需要占用系统资源的,所有建议空闲的时候进行增、减磁盘。如果磁盘组有故障组(镜像)的设置,那么数据文件在每个故障组当中都有完整的冗余备份。1个或多个磁盘 / 磁盘分区构成1个故障组,交由1个磁盘控制器进行管理,多个故障组构成ASM磁盘组。ASM有3种镜像类型设置:外部冗余(external redundancy, 不在ASM下实现冗余,例如RAC、磁盘阵列等等)、常规冗余(normal redundancy, 保留多1份)、高冗余(high redundancy, 保留多两份)。
2. 配置ASM
 安装软件包
查看当前已经安装的包
[root@RedQueen ~]# rpm -qa | grep asm
需要安装的包:
· oracleasm-support -- 由于用的是OEL,操作系统内核已经集成,不需要另外再安装
· oracleasmlib
官方文档:Installing and Upgrading – Database Installation Guide for Linux – Oracle Grid Infrastrature. Ctrl + F: “http”. 下载并上传到root用户下;
[root@RedQueen ~]# rpm -ivh oracleasmlib …
rpm -qa | grep asm
 配置用户、用户组
[root@RedQueen ~]# groupadd asmadmin
groupadd asmdba
groupadd asmoper
useradd -g oinstall -G asmdba,asmadmin,asmoper,dba grid
passwd grid
usermod -G dba,asmdba,asmadmin oracle
 配置目录
[root@RedQueen ~]# mkdir -p /u01/app/grid -- $ORACLE_BASE
mkdir -p /u01/app/oracle/product/11.2.0/grid -- $ORACLE_HOME
chown -R grid:oinstall /u01/app/grid /u01/app/oracle/product/11.2.0/grid
 配置文件
[root@RedQueen ~]# vi /etc/security/limits.conf
grid soft nproc 2047
grid hard nproc 16384
grid soft nofile 1024
grid hard nofile 65536
grid soft stack 10240
 配置环境变量
[grid@RedQueen ~]$ vi .bash_profile
export ORACLE_SID=+ASM
export ORACLE_BASE=/u01/app/grid
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/grid
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
source .bash_profile
 创建ASM磁盘
虚拟机添加磁盘
查看磁盘是否能被识别
[root@RedQueen ~]# fdisk -l
在线添加磁盘(识别)
[root@RedQueen ~]# echo “- - -” > /sys/class/scsi_host/host2/scan
fdisk -l
创建主分区(可选,或者使用多路径的方式也可以)
[root@RedQueen ~]# fdisk /dev/sdb
/** fdisk /dev/sd(b, c, d, e … ) 根据提示创建
Command (m for help): -- n 新建磁盘分区;p 查看当前创建了的主分区;w 保存*/
fdisk -l
配置ASMlib驱动
[root@RedQueen ~]# /etc/init.d/oracleasm configure
Default user to own the driver interface []: <grid>
Default group to own the driver interface []: <oinstall>
Start Oracle ASM library driver on boot (y/n) [n]: y
Scan for Oracle ASM disks on boot (y/n) [y]: y
创建ASM磁盘
[root@RedQueen ~]# oracleasm createdisk <VOL1> /dev/sdb1 -- sdc1, sdd1, sde1 …
ls /dev/oracleasm/disks/
 安装ASM
[grid@RedQueen ~]$ unzip *Linux-x86-64_3of7*.zip
ll
cd ./grid/
./runInstaller
Checking monitor: must be configured to display at least 256 colors
>>> Could not execute auto check for display colors using command /usr/bin/xdpyinfo. Check if the DISPLAY variable is set. Failed <<<<
[root@RedQueen ~]# xhost +
[grid@RedQueen grid]$ ./runInstaller
[grid@RedQueen ~]$ sqlplus / as sysasm -- ASM
SQL> SELECT INSTANCE_NAME FROM v$instance; -- +ASM.
SELECT status FROM v$instance; -- STARTED
shutdown immediate
ORA-15097: cannot SHUTDOWN ASM instance with connected client
exit;
[oracle@RedQueen ~]$ sqlplus / as sysdba -- RDBMS
SYS@Orcl> SELECT name FROM v$datafile; -- +<DiskGroup_name>/<oracle_sid>/datafile/ …
show parameter recover -- db_recovery_file_dest: +RECOV
SELECT status FROM v$instance; -- OPEN
shutdown immediate
startup -- 没有打开ASM实例
ORA-01078: failure in processing system parameters
ORA-01565: error in identifying file ‘+<DiskGroup_name>/<oracle_sid>/ … ’
ORA-17503: ksfdopn: n Failed to open file +<DiskGroup_name>/<oracle_sid>/ …
ORA-15077: could not locate ASM instance serving a required diskgroup
3. 管理ASM
 创建ASM磁盘组
先创建ASM磁盘,再创建ASM磁盘组。
CREATE DISKGROUP <DiskGroup_name>
[HIGH | NORMAL | EXTERNAL REDUNDANCY]
[FAILGROUP <FailGroup_name>]
DISK ‘<ORCL:VOL4>’, ‘<ORCL:VOL5>’ [NAME <disk_name>] [SIZE <size_clause>] [FORCE | NOFORCE]
[grid@RedQueen ~]$ sqlplus / as sysasm
SQL> SELECT NAME, TYPE FROM v$asm_diskgroup;
SELECT NAME, GROUP_NUMBER, FAILGROUP FROM v$asm_disk;
 删除磁盘组
SQL> DROP DISKGROUP <DiskGroup_name>;
SELECT NAME, TYPE FROM v$asm_diskgroup;
 向磁盘组添加 / 删除磁盘
SQL> ALTER DISKGROUP <DisGroup_name> ADD | DROP DISK ‘<[ORCL:]VOL4>’ NAME <dg1_vol4>;
SELECT NAME, GROUP_NUMBER, FAILGROUP FROM v$asm_disk;
-- 不能删除唯一的磁盘,或者使磁盘数量低于冗余度。
 查看磁盘剩余空间
SQL> SELECT NAME, GROUP_NUMBER, FAILGROUP, FREE_MB FROM v$asm_disk;
 调节再平衡速度
SQL> show parameter asm_power_limit
-- 默认值为1,数值越大越快,越占用系统资源。
 手动平衡磁盘组
SQL> ALTER DISKGROUP <data> REBALANCE POWER n;
 卸载磁盘组
SQL> ALTER DISKGROUP <DiskGroup_name> DISMOUNT;
ORA-15032: not all alterations performed
ORA-15027: active use of diskgroup “<RECOV>” precludes its dismount
SELECT group_number, name, state, type FROM v$asm_diskgroup;
P.S.
[grid@RedQueen ~]$ asmca -- 可以帮助创建ASM磁盘组、ASM实例。
4. 管理OMF文件
 创建 / 删除 / 重命名目录
SYS@+ASM> ALTER DISKGROUP <DiskGroup_name> ADD | DROP DIRECTORY ‘<+DG/dir>’ [FORCE];
-- FORCE, 强制删除下面的子目录。
ALTER DISKGROUP <DiskGroup_name> RENAME DIRECTORY ‘<+DG/dir_old>’ TO ‘<+DG/dir_new>’;
 添加 / 修改 / 删除别名
SYS@+ASM> ALTER DISKGROUP <DiskGroup_name> ADD | RENAME | DROP ALIAS ‘<+DG/dir/users.dbf>’ FOR ‘<+DG/dir/users … >’;
-- 目录下会同时有原名、别名,但指向同一个文件。
 Asmcmd工具管理ASM
[grid@RedQueen ~]$ asmcmd
ASMCMD> help
/** 查看可用命令。如:
cd、cp、du、find、help、ls、lsct(列出连接了的客户端)、lsdg(列出磁盘组)、lsof(列出所有的文件)、mkalias、mkdir、pwd、rm、rmalias
lsdsk(列出磁盘)、lsod(列出磁盘信息)、mkdg(创建磁盘组)、dropdg(删除磁盘组)
shudown、startup、spbackup、cpcopy、spget、spmove、spset(关于参数文件的命令)
chgrp、chmod、chown、lsgrp、lsusr、mkusr */
ASMCMD> help <find>
find <+data> <undo*> | find --type <CONTROLFILE> <+data/orcl>
help <mkdg>
mkdg <data_coonfig.xml> …
help <dropdg>
dropdg -r -f <data>
help lsgrp
lsgrp <%asm%> | lsgrp -a
二十六、 闩和锁
闩Latch用于保护共享内存中的数据,避免在同一时刻被两个或以上的进程进行修改(需要串行化,Oracle在Buffer Cache、Shared Pool、Log Buffer都有各式各样的闩)。锁Lock用于控制多个用户对表里相同数据的访问,它的数据资源相对复杂,需要有一定的逻辑判断。闩是一种轻量级的锁(可以理解为一个变量值判断),获得与释放的速度快;锁可以持续很长时间,使用队列先进先出的方式。
1. 闩
闩Latch分为两种:愿意等待(大多数)、不等待。愿意等待就是当前进程不能获得Latch的时候,会占用CPU空转(SPIN CPU),进行等待(因为Latch是一个很快速的动作,如果放弃CPU资源,就要进行上下文切换,再次获得CPU的时候,又要再一次上下文切换,花费更多时间)。如果尝试获得Latch的次数超过某个上限的时候,进程会释放CPU,进入sleep状态[0.01 * 2^(n - 1)]秒(最大值0.2秒),抛出一个等待事件,并记录在v$session_wait视图里。如果只有1个CPU,一旦获得不了Latch,就sleep,不空转CPU;不等待就是当一个Latch不可用,就请求另外一个Latch,只有所有的Latch都不可用才等待。
如果CPU利用率过高,考虑以下原因:SQL语句没有使用绑定变量,导致Oracle对每一条语句都进行硬解析,也就是非常频繁地读写Shared Pool里面的数据块,从而导致Latch争用、等待;SQL语句低效,导致扫描很多的数据块才能返回Resultset(查找数据块也要获得Latch,直到找到数据块,Latch争用,CPU繁忙)。
2. 锁
锁Lock分为两种情况:排它锁(X锁)、共享锁(S锁,不能再加X锁,只能添加S锁);DML事务锁定机制有两种锁:表级锁、行级锁(TX锁,只有X锁,没有S锁)。
i. Oracle解析SQL语句,找到数据块、undo数据块,将旧值放入undo数据块;
ii. 在数据块头部分配一个ITL事务槽,存放事务ID、SCN号、undo数据块地址、事务未提交的标记;
iii. 在数据块中找到数据行,在数据行头部设置被锁定的标记(实际上还会添加一个表级锁,避免其他用户进行表级操作),记录ITL事务槽号码;
iv. 数据行已经添加了X锁,控制权交给用户。
v. 当其他用户的进程发现SELECT的记录有锁定标记的时候,会在数据行头部找到ITL事务槽,进而找到undo数据块,讲旧值取出来,构建读一致性CR块。
给表添加锁:
LOCK TABLE <tab>
IN ROW SHARE | ROW EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE MODE;
A. 共享锁Shared(S)
加锁语法:
LOCK TABLE <tab> IN SHARE MODE; -- 锁定整个表
SELECT … FOR UPDATE; -- 锁定行
允许操作:添加RS锁。
禁止操作:任何用户更新表。参考表格。
B. 排它锁Exclusive(X)
限制最多的一种锁。
加锁语法:LOCK TABLE <tab> IN EXCLUSIVE MODE;
允许操作:仅允许其他事务进行查询。
禁止操作:其它事务进行DML、DDL操作。

注释:
共享锁、排它锁的区别在于是否允许添加RS锁。
C. 行级共享锁Row Shared(RS)
限制最少的一种锁。有时称为子共享锁Subshare Table Lock, SS.
加锁语法:
SELECT … FROM <tab> FOR UPDATE [OF … ];
LOCK TABLE <tab> IN ROW SHARE MODE;
允许操作:其它事务对其它数据行进行DML操作、添加RX锁。
禁止操作:其它事务对表添加X锁。主要是用户不希望其它用户对所查询的数据进行更新。

D. 行级排它锁Row Exclusive(RX)
有时称为子排它锁Subexclusive Table Lock, SX.
加锁语法:
INSERT INTO | UPDATE | DELETE FROM <tab> … ;
LOCK TABLE <tab> IN ROW EXCLUSIVE MODE;
允许操作:其它事务对其它数据行进行DML操作、使用LOCK命令对表添加RX锁。
禁止操作:不允许其它事务对表添加X锁。

E. 共享行级排它锁Shared Row Exclusive(SRX)
有时称为共享子排它锁Share Subexclusive Table Lock, SSX.
加锁语法:LOCK TABLE <tab> IN SHARE ROW EXCLUSIVE MODE;
允许操作:其它事务使用SELECT * FROM <tab> FOR UPDATE来锁定行而防止更新。
禁止操作:对表进行DML操作、添加共享锁。

RS RX S SRX X
RS √ √ √ √ X
RX √ √ X X X
S √ X √ X X
SRX √ X X X X
X X X X X X
注释:
- 所有的锁加了之后,都不能drop表
- 只有RS、RX锁加了之后,可以进行DML操作
- INSERT语句会发生阻塞的唯一情况:INSSERT INTO建有主键约束的表
F. 锁的视图
视图 信息
V$TRANSACTION 当前每个活动事务的信息
V$LOCK 已经获得的锁定、正在请求的锁定
V$ENQUEUE_LOCK 跟v$lock一样,但只显示申请锁定,又无法获得锁定的信息
V$LOCKED_OBJECT 已经被锁定的对象
V$SESSION 当前session信息
查看是否有死锁:
SELECT sid, id1, id2, lmode, request, type FROM v$lock WHERE id1 IN (
SELECT id1 FROM v$lock WHERE lmode = 0
) ORDER BY id1, request;
SELECT sid, type, id1, id2,
decode(lmode, 0, ‘none’, 1, ‘null’, 2, ‘row share’, 3, ‘row exclusive’, 4, ‘share’, 5, ‘share row exclusive’, 6, ‘exclusive’) lock_type, -- TM: 表级锁,行级排它锁;TX: 排它锁。
request, ctime, block
FROM v$lock WHERE type IN (‘’,’’);
查看SID:
SELECT sid FROM v$mystat WHERE rownum = n;
根据SID查看锁:
SELECT sid, type, id1, id2,
decode(lmode, 0, ‘none’, 1, ‘null’, 2, ‘row share’, 3, ‘row exclusive’, 4, ‘share’, 5, ‘share row exclusive’, 6, ‘exclusive’) lock_mode,
decode(request, 0, ‘none’, 1, ‘null’, 2, ‘row share’, 3, ‘row exclusive’, 4, ‘share’, 5, ‘share row exclusive’, 6, ‘exclusive’) request_mode, block
FROM v$lock WHERE sid = n;
查看对象:
SELECT object_name FROM dba_objects WHERE object_id = n;
查看被锁定的SID、以及对象名称:
SELECT l.os_user_name, s.username, s.sid, s.serial#,
decode(l.locked_mode, 0, ‘none’, 1, ‘null’, 2, ‘row share’, 3, ‘row exclusive’, 4, ‘share’, 5, ‘share row exclusive’, 6, ‘exclusive’) lock_type,
o.object_name, o.object_type, s.logon_time
FROM v$locked_object l, v$session s, dba_objects o
WHERE l.session_id = s.sid
AND l.object_id = o.object_id
ORDER BY s.logon_time;

SELECT l.oracle_user_name o_name, l.session_id sid,
decode(l.locked_mode, 0, ‘none’, 1, ‘null’, 2, ‘row share’, 3, ‘row exclusive’, 4, ‘share’, 5, ‘share row exclusive’, 6, ‘exclusive’) lock_type,
o.object_name, o.object_type, l.xidusn, l.xidslot, l.xidqsn
FROM v$locked_object l, all_objects o
WHERE l.object_id = o.object_id
ORDER BY s.logon_time;

SELECT p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username, b.os_username
FROM v$process p, v$session a, v$locked_object b, all_objects c
WHERE p.addr = a.paddr
AND a.process = b.process
AND c.object_id = b.object_id;
查看引起锁的SQL语句:
SELECT count(1) FROM v$lock WHERE lmode = 0;
SELECT sql_text FROM v$sql WHERE hash_value in (
SELECT sql_hash_value FROM v$session WHERE sid IN (
SELECT session_id FROM v$locked_object
)
);
查看锁的信息:
SELECT t2.username, t2.sid, t2.serial#, t2.logon_time
FROM v$locked_object t1, v$session t2
WHERE t1.session_id = t2.sid
ORDER BY t2.logon_time;
杀掉死锁进程:
ALTER SYSTEM KILL SESSION ‘sid, serial#’;
禁止表锁 / 加锁:
ALTER TABLE <tab> DISABLE TABLE LOCK;
SELECT table_name, table_lock FROM user_tables;
 避免死锁的方法
约定不同的程序员按照一定的顺序对不同的表依次加锁;
首先申请高限制的锁,再申请低限制的锁;
使用完该行后即时释放(例如在更新语句后马上判断提交或回滚)。
二十七、 优化
官方文档 – 优化:Database Administration – Performance Tuning Guide – SQL Access Advisor.
http://docs.oracle.com/cd/E11882_01/server.112/e10822/toc.htm
官方文档 – hint:
http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements006.htm#SQLRF50701
1. 索引
Oracle的RDBMS访问数据时,最根本地会使用三种访问方法:全表扫描、ROWID、索引。只有当使用全表扫描的时候,Oracle会采用多块读的方式(通过db_file_multiblock_read_count参数进行控制),如果读取的数据超过总的数据5% ~ 10%,通常就会使用全表扫描;而ROWID则是最快的方式,又能区分重复的数据;索引比较小,主要存放的是索引键值、ROWID,一般是直接缓存到内存里的,适用于DML操作比较少的大表。索引第一部需要进行逻辑读(ROWID),第二步进行物理读(数据)
A. 索引类型
 B树索引(默认)
需要根节点、分支节点、叶子节点、表中数据这4次I/O就可以完成查找数据,所以B树索引是高度平衡、性能平衡的索引。叶子节点实际上是个双向链表,所有叶子都在同一层上,索引的高度 = 层数 - 1. (高度不把叶子节点计算在内)。
B树索引适合于重复率低的字段,例如主键等。如果重复率高,Oracle优化器会走全表扫描,一致性读会远高于4次。可以使用hint(/* +index( <tab> <tab_index>) */)来强制使用索引扫描,只不过一致性读的成本会更高而已。
查看索引信息:
SELECT index_name, blevel, num_rows FROM user_indexes WHERE table_name = ‘’;
查看访问数据信息:
SYS@Orcl> SET AUTOTRACE TRACEONLY
SELECT * FROM …
… 4 consistent gets … -- 4次一致性读。
 反向键索引
CREATE INDEX <ind> ON <tab>(<col>) REVERSE;
实际上就是B树索引。反向键索引适用于索引值是按照序列值递增,而又需要插入大量数据的情况,
 排序索引
语句的排序,要跟索引的排序匹配,才能用得上。
CREATE INDEX <ind> ON <tab>(<col1> desc, <col2> asc) [TABLESPACE <tbs>];
SELECT * FROM <tab> WHERE … ORDER BY <col1> desc, <col2> asc;
 位图索引
CREATE BITMAP INDEX <ind> ON <tab>(<col>);
适合于重复值多、更新较少的数据仓库使用,因为每个位图索引项与表中大量的行都有关联,修改一个位图索引段会影响整个位图索引段,而且更新索引的时候,索引还需要被锁定,所以不适用于DML操作频繁的OLTP系统。
B树索引可以实现行级锁定,但是位图索引由于对ROWID是进行压缩存放的,所以每次锁定的都是ROWID范围。因此在对位图索引列进行更新的时候,容易导致死锁,并发性很差。
位图索引有很多限制:
- 基于规则的优化器不会考虑位图索引;
- 执行ALTER TABLE语句并包含索引列的时候,位图索引会失效;
- 位图索引不包含列数据,不能进行任何完整性检查(主键、唯一性约束等);
- 位图索引不能声明为唯一索引;
- 位图索引最大长度是30.

查看索引大小:
SELECT segment_name, bytes FROM user_segments
WHERE segment_type = ‘INDEX’ AND segment_name = ‘’;
 函数索引
并不是一个好的practice,但有需要的时候就建立。
CREATE INDEX <function_index> ON <tab>(<2*col-1>) [TABLESPACE <tbs>];
B. 维护索引
启用 / 关闭索引监控:
ALTER INDEX <ind> MONITORING [NOMONITORING] USAGE;
查看索引使用情况:
SELECT index_name, table_name, monitoring, used FROM v$object_usage;
重建索引:
ALTER INDEX <ind> REBUILD [TABLESPACE <tbs> /*迁移索引*/]
合并索引碎片:
ALTER INDEX <ind> COALESCE;

SELECT index_name, blevel, clustering_factor FROM dba_indexes WHERE owner = ‘SCOTT’;
SELECT index_name, distinct_keys/num_rows FROM user_indexes;
-- distinct_keys/num_rows = 1为最佳,也就是unique key。
P.S.
由于空值不入索引,所以设计表的时候,一般索引列都是需要有非空约束的。
ALTER TABLE <tab> MODIFY (<col> NOT NULL);
2. 优化器
Oracle有两种优化器,基于成本的优化器(Cost-Based Optimzer, CBO, 默认)和基于规则的优化器(Rule-Based Optimizer, RBO, 供Oracle内部使用,不再使用它来生成用户的执行计划)。CBO会根据系统和数据库统计数据、数据字典统计信息(所以统计信息需要是最新的),来计算SQL每个执行计划的I/O次数和CPU周期数,从而选择出最佳的执行计划。它是SQL执行的核心。
OPTIMIZER_MODE 优化目标
ALL ROWS 默认,实现查询的最大吞吐量
FIRST_ROWS_N 快速响应查询需求

 动态采样
CBO可以通过动态采样来获得表中数据的实际情况(例如数据量等)。
3. 执行计划Execution Plan
执行计划是指SQL语句在Oracle中的执行过程或者访问路径的一种描述。
执行计划存放于共享池 – 库高速缓存 – 共享SQL区。
如果一条SQL平时执行得很好,有一天性能却很差,那要么是系统资源和阻塞的原因,要么就是执行计划出了问题(例如统计信息不准确等)。
启用执行计划:
SCOTT@Orcl> SET AUTOTRACE ON
SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled
SP2-0611: Error enabling STATISTICS report
sqlplus / as sysdba
SYS@Orcl> @$ORACLE_HOME/rdbms/admin/utlxpls.sql
/*创建表plan_table,用于观察执行计划。*/
@$ORACLE_HOME/sqlplus/admin/plustrce.sql -- 创建plustrace角色
GRANT plustrace TO scott; -- 授权
收集统计数据信息:
SYS@Orcl> EXECUTE dbms_stats.gather_table_stats(‘<u01>’, ‘<tab>’, cascade=>true); -- 表
EXECUTE dbms_stats.gather_schema_stats(ownname=>’<scott>’); -- 模式
EXECUTE dbms_stats.gather_index_stats(‘<scott>’, ‘<ind>’); -- 索引
EXECUTE dbms_stats.gather_database_stats(estimate_percent=>null); -- 数据库
EXECUTE dbms_stats.gather_system_stats(‘NOWORKLOAD’, 10); -- 操作系统
EXECUTE dbms_stats.gather_fixed_object_stats; -- 固定字典表
EXECUTE dbms_stats.gather_dictionary_stats; -- 数据库字典表
EXECUTE dbms_stats.gather_schema_stats(‘<sys>’); -- 数据字典
查看执行计划:
EXPLAIN PLAN FOR …
SELECT * FROM table(dbms_xplan.display);
查看Execution Plan的时候,应该是从内向外看的。查看成本(Cost, 它是一个相对值,是没有单位的)、还有“*”注释。
在统计信息中,主要看:
- recursive call, 递归调用。第一次执行语句的时候,需要将数据调到内存中去。第二次就不需要递归调用了。
- db block gets, 即时读,读内存。执行UPDATE / DELETE操作的时候会使用即时读模式。
- consistent gets, 一致性读,读内存中回滚段的一致性影像。执行SELECT操作的时候会使用一致性读模式。
·官方文档:Database Administration – Database Concepts – Memory Architecture, Ctrl+F “Buffer Mode”.
Logic I/O = db block gets + consistent gets.
Consistent gets = numrows / arraysize + blocks.
/* show arraysize;
SELECT blocks, num_rows, empty_blocks FROM dba_tables WHERE table_name = ‘’;
所以不建议将arraysize设置得很低。可以参考Execution Plan里面的“SQL*Net roundtrips to / from client”的值。
- physical reads, 读磁盘。
- redo size。执行SELECT语句也有可能产生redo size,主要是由于UPDATE大量数据的时候,Oracle会延迟块清除,延迟到下一次对其进行操作的时候(对比于快速块清除block clean out, 马上将脏数据变成干净数据)。
如果执行计划的字段行数的统计信息跟索引的行数不同,需要给Oracle优化器手工设置统计信息(手动设置可以降低系统资源消耗):
SYS@Orcl> EXECUTE dbms_stats.set_table_stats (<user>, ‘<tab>’, method_opt=>’for all indexed columns size <n>’ cascade=TRUE);
| EXECUTE dbms_stat.set_column_stats (ownname=><user>, tabname=>’<tab>’, colname=>’<col>’, nullcnt=>0, density=>1/<disctinct_key_amount>, distcnt=><distinct_key_amount>);
 执行计划中扫描数据的方式:
TABLE ACCESS FULL -- 全表扫描
TABLE ACCESS BY USER ROWID -- ROWID
… TABLE ACCESS BY INDEX ROWID -- 索引
查看行平均长度:
SELECT avg_row_len FROM user_tables WHERE table_name = ‘’;
/*那么表的大小 = rows * avg_row_len / 1024. */
A. 索引扫描方式
- 索引唯一扫描Index Unique Scan
通过唯一键 / 主键,通常是让Oracle返回一行数据。
例:SELECT * FROM <tab> WHERE <unik> = … ;
- 索引全扫描Index Full Scan
查询的数据(列)全部都能从索引中得到的时候会使用。它是排序的,不并行。
例:SELECT * FROM <tab> … ORDER BY … ; / count(*)
-- count(1)比count(*)速度快,当有主键的时候,应该使用count(<col>)。
- Index Full Scan(min / max)
例:SELECT min(col) | max(col) FROM <tab>;
当选择率较高的时候(5%左右,但不一定。它是一个默认的参数值,可以调,但是不太建议去调),不需要使用索引,因为查看索引也是需要成本的;当选择率比较低的时候,可以考虑使用hint,去强制使用索引,例如:/*+ INDEX(<tab>, <index>) */;/*+ USE_HASH(<tab1>, <tab2>)*/;/*+ USE_NL(<tab1> <tab2>)*/ -- Nested Loop。
- 索引快速扫描Index Fast Full Scan
扫描索引块中的数据,但没有排序操作,这样Oracle就可以多块读,也可以并行读。
例:SELECT * FROM <tab>;
- 索引范围扫描Index Range Scan
在唯一键上使用range操作符(>, <, between … ),或者查询出多行数据,而且行数远小于全表行数的时候,会使用索引范围扫描。
例:SELECT * FROM <tab> WHERE <col> BETWEEN … AND … ;
- Index Skip Scan
数据高度一致的时候会使用。
 限制使用索引的情况
在WHERE子句中使用了不等于运算符、is [not] null、函数(除非已经建立了相应的函数索引),都会走全表扫描。
B. Hint
官方文档:Database Administration – Performance Tuning Guide – Using Optimizer Hints.
hint语法主要有关于优化器、以及访问路径(Full、Index)的,还有以下关于以下方面:Optimization Approaches and Goals (optimizer_mode), Enabling Optimizer Features (optimizer_features_enable), Join Orders, Join Operations (use_nl, use_merge, use_hash), Online Application Upgrade, Parallel Execution, Query Transformations, Additional Hints.
改变SQL执行计划。
如果表指定了别名,那么hint中必须使用别名。

格式 说明
优化器相关
/* +ALL_ROWS */
/* +FIRST_ROWS_N */ 优先显示前n行数据
/* +RULE+ */ 强制使用RBO优化器
访问路径相关
/* +FULL(<TAB>) */ 使用全表扫描访问数据
/* +[NO_]INDEX(<TAB> <INDEX>) */
/* +INDEX_DESC(<TAB> <INDEX>) */
/* +INDEX_COMBINE(<TAB> <INDEX>) */
/* +INDEX_FFS(<TAB> <INDEX>) */
/* +INDEX_JOIN(<TAB> <INDEX1> <INDEX2>) */
/* +INDEX_SS(<TAB> <INDEX>) */ (不)使用索引访问数据
降序使用索引访问数据
位图索引
Fast Full Scan索引快速扫描
索引关联
index Skip Scan
表关联相关
/* +LEADING(<TAB1>,<TAB2>) */ tab1作为驱动表
/* +USE_HASH(<TAB1>, <TAB2>) */ hash join
/* +USE_MERGE(<TAB1>, <TAB2>) */ merge join
/* +USE_NL(<TAB1>, <TAB2>) */ nested loop
并行执行相关
/* +PARALLEL(<TAB> N) */ 设置并行度
其它方面
/* +APPEND */ 以直接append的方式将数据插入表
/* +DYNAMIC_SAMPLING(<TAB> 0) [CARDINALITY(<TAB> N)] */ CBO优化器的动态采样(0表示关闭,cardinality设置行数)

C. 表连接
需要首先搞清楚表的大小情况,才能更好地确定执行计划是否正确。例如两个大表之间进行连接,应该使用Hash Join;子查询的结果集比较小的时候,应该使用嵌套循环Nested Loop。
驱动表又称外层表;被探查表又称内层表。
 小表连接大表
应该把小表作为驱动表,然后在大表的连接列上做索引,这样成本比较小。因为:
当小表Tab1作为驱动表、大表Tab2上做索引的时候,它的成本是:
Cost A = Full Scan on Tab1 + Tab1_row_count * 1(time) * Index read on Tab2.
Cost B = Full Scan on Tab2 + Tab2_row_count * Full Table Scan on Tab1.
索引需要查看一下执行计划,是否为嵌套循环Nested Loop等等,考虑使用hint的方式强制一下。
 两个大表连接
两个大表,进行等值连接,其中一个略小一点,应该使用Hash Join。利用小表创建一个Hash Table (实际上就是key – value对)(如果内存不够,Oracle会自动分割成几个小的Hash Table),在大表上进行索引定位。
这样相对上是消耗了一定量的CPU、内存(最好保证足够内存,否则就会分页,降低了性能,最后导致解析器选择了错误的连接模式join mode)资源,相对而言可以接受,它的成本也相当于全表扫描Full Table Scan。
 两个超级大表连接
SELECT * FROM <tab1>, <tab2> WHERE <tab1>.<col1> = <tab2>.<col1>;
首先在表1和表2结构的基础上多加一个字段hash_value,并根据hash_value进行分区:
CREATE TABLE <partition_tab1>( … )
PARTITION BY LIST(hash_value) (
PARTITION p0 VALUES (0),

);

CREATE TABLE <partition_tab2>( … )
PARTITION BY LIST(hash_value) (
PARTITION p0 VALUES (0),

);
删除表1和表2中,<col1>为空的行:
DELETE <tab1> WHERE <col1> IS NULL;

DELETE <tab2> WHERE <col1> IS NULL;
插入数据:
INSERT INTO <partition_tab1>
SELECT ORA_HASH(col1, n), <tab1>.* FROM <tab1>;

INSERT INTO <>partition_tab2>
SELECT ORA_HASH(col1, n), <tab2>.* FROM <tab2>;
查询数据:
SELECT *
FROM <partition_tab1>, <partition_tab2>
WHERE <partition_tab1>.<col1> = <partition_tab2>.<col1>
AND <partition_tab1>.hash_value = 0
AND <partition_tab2>.hash_value = 0;

P.S.
最好将两个基本有序的结果集进行合并。

 绑定变量
如果使用绑定变量,那么第二次的解析计划会以第一次为准,所以需要注意两次的选择率是否大致一样,考虑是否需要修改cursor_sharing参数。
 RAC
在RAC环境下,节点与节点之间会相互进行通讯,从而进行内存交换,而不会多次执行同样的执行计划Execution Plan。因此性能的瓶颈会有可能出现在网络上,所有不是说节点越多就越好的(比较常用的是采用两三个节点)。比较好的做法one of the Best Practice是:对业务逻辑进行拆分,不同的app (逻辑)访问不同的节点。
 读写分离
读写分离一般的思路是建立主、副两份表,分别进行读、写。而读写分离的工具有很多,例如Golden Gate, 它是将那些,对主表进行修改的、经过分析的result,传给副表;还有StandBy, 它是将修改主表的log,传给副表的。
 水平分割、垂直分割
水平分割可以理解为分区partition的思想;而垂直分割则可以理解为冗余duplication的思想,以空间换时间。
· 范式并非越高越好的,甚至有时候需要反规范化来达到我们所预期的效果
P.S.
考虑使用Java code / package.function、架构上进行平衡,不要把性能瓶颈积压在SQL身上。例如:




4. statistics、AWR和ASH
A. statistics
statistics收集的是过去某个时间段信息的性能分析报告,通过快照来指定开始点和结束点。
安装statistics:
SYS@Orcl> @?/rdbms/admin/spcreate.sql
show user
USER is “perfstat”
卸载statistics:
SYS@Orcl> @?/rdbms/admin/spdrop.sql
创建快照:
PERFSTAT@Orcl> execute statspack.snap
生成报告:
PERFSTAT@Orcl> @?/rdbms/admin/spreport.sql
[oracle@RedQueen ~]$ vi <sp_1_2.lst>
B. ASH (Active Session History)
v$session_wait_history保留了v$session_wait中最近10次的等待事件;而v$active_session_history则是用于监测一段时间内数据库性能状况的,它每秒钟从v$session_wait采样一次,将最近5 ~ 10分钟的相关等待信息保留在内存中,来诊断当前数据库的状态。AWR时间间隔为1小时,ASH的周期是5分钟左右。
但由于是保存在内存(关机消失)中,而且空间有限,所以无法长期监测Oracle性能,因此有了AWR;ASH和AWR都是通过相关会话的等待信息,来分析数据库性能状态的,只不过AWR比ASH收集的信息更多更全面。
查看ASH大小:
SELECT pool, name, byte/1024/1024 M FROM v$sgastat WHERE name like ‘%ASH %’;
生成ASH报告:
SYS@Orcl> @?/rdbms/admin/ashrpt.sql
 Top Events
- Top Backgroud Events、Top Sessions
如果显示No data exists for this section of the report, 表明这个部分没有性能问题。
C. AWR (Automatic Workload Repository)
报告内容基本与statistics相同,不过AWR信息更加全面,而且支持HTML格式(可以生成text格式),方便阅读。AWR的数据来源于AWR视图dba_hist_* (例如dba_hist_active_sess_history),存放于wrh$_active_session_history视图中(SYS@Orcl> SELECT * FROM wrh$_active_session_history; )。AWR报告由Oracle自动产生,默认保留8天。
快照是由MMON和MMNL后台进程自动进行采样的。MMON负责执行和管理相关的后台任务(包括快照采样);MMNL负责轻量级、频率高的后台任务(例如捕获历史信息)。
采样数据存储在SYSAUX辅助表空间的表(WRM$_*和WRH$_*, 可以从dba_tables视图查看)当中。当SYSAUX表空间不足的时候,警告日志会有ORA-1688的提示:unable to extend table SYS.WRH$_ACTIVE_SESSION_HISTORY partition … by n in tablespace SYSAUX. 初始化参数statistics_level (basic, typical (默认), all)可以设置采样的数据量。
基线是正常状态的标准,定义在一对快照之间,每条基线有且只有一对快照。
创建快照:
SYS@Orcl> EXECUTE dbms_workload_repository.create_snapshot
删除快照:
SYS@Orcl> SELECT dbid FROM v$database;
BEGIN
dbms_workload_repository.drop_snapshot_range(
low_snap_id => n,
high_snap_id => m,
dbid => a );
END;
/
创建基线:
SYS@Orcl> EXECUTE dbms_workload_repository.create_baseline(<snap_n>, <snap_m>, ‘<name>’);
删除基线:
SYS@Orcl> EXECUTE dbms_workload_repository.drop_baseline(baseline_name=>’<name>’, cascade=>false);
修改采样时间、保留时间:
SYS@Orcl> SELECT * FROM dba_hist_wr_control;
EXECUTE dbms_workload_repository.modify_snapshot_settings(interval=>120, retention=>14*24*60);
SELECT * FROM dba_hist_wr_control;
生成报告:
PERFSTAT@Orcl> @$ORACLE_HOME/rdbms/admin/awrrpt.sql
ERROR at line 1:
ORA-00904: : invalid identifier
SYS@Orcl> @$ORACLE_HOME/rdbms/admin/awrrpt.sql
a. AWR报告主要信息
官方文档:Database Administration – Database Concepts – Memory Architecture
Elapsed < DB Time, 数据库有性能问题。DB Time是指前台session花在database调用上的时间,例如CPU时间、I/O时间等,描绘了数据库总体的负载情况。
 Report Summary
- Cache Sizes
缓冲区如果分配过小,LRU算法将频繁地将数据剔除内存,写入数据文件的同时还要读取数据,导致I/O、CPU的负荷加大。又例如,如果共享池设置过小,导致数据字典缓冲区过小,执行SQL进行递归调用的时候查询数据字典就不够用;共享SQL区的大小也会不够,造成保存的执行计划很少,也就是会执行更多的硬解析。
- Load Profile (负载信息)
Parses, Hard parses:
如果值过大,说明硬解析数量过多,数据库存在性能问题
Redo size:
如果Per Second的值比较大,说明DML操作比较多,是OLTP系统。
Logical reads, Physical reads:
逻辑读读内存,主要消耗CPU资源;物理读读磁盘,主要消耗I/O。
- Instance Efficiency Percentage (Target 100%)
Buffer Nowait, Redo Nowait:
Redo Nowait接近100%, 说明redo log buffer和redo log file,甚至于归档文件的设置都比较合理,LGWR运行比较流畅。
Buffer Hit:
In-memory Sort:
PGA有排序区,说明PGA设置没有问题。
Library Hit:
库高速缓存没有问题。
Sort Parse:
百分比越高,共享的执行计划就越多。如果比较低,就考虑使用绑定变量、SQL书写规范等等。
Execute to Parse:
Latch Hit:
内存中Latch的命中率。
- Shared Pool Statistics
Memory Usage:
内存使用情况。应该稳定在75% ~ 90%之间,过小说明共享池有浪费,过大说明共享池有争用,内存不足。
SQL with executions > 1:
SQL执行大于1次的百分比。如果值过小,说明需要使用更多的绑定变量,避免过多硬解析。
- Top 5 Timed Foreground Events
官方文档:Database Administration – Reference – Oracle Wait Events – Next -> Classes of Wait Events.
性能优化切入点。等待事件主要分为空闲、非空闲两种,可以通过v$event_name视图查看。
查看等待事件类型:
SELECT wait_class#, wait_class_id, wait_class, count(1) AS count FROM v$event_name
GROUP BY wait_class#, wait_class_id, wait_class
ORDER BY wait_class#;
如果DB CPU处于等待事件的第一位,基本上没有性能问题。
db file sequential read (单块读):
指的是将数据块读入到相连的内存空间当中(contingous memory space),而不是指所读取的数据块是相连的。平均单次等待时间应该小于20ms。常见情况有:索引访问、回滚操作、ROWID方式访问数据、重建控制文件等。如果这个等待事件比较明显,则表示可能在多表连接中,表的连接顺序有问题,即可能没有正确地选择驱动表;或者是使用索引不合理。
enq: TX – row lock contention:
行级锁的问题。考虑事务操作的先后顺序问题。
Log File Sync:
用户提交或回滚的时候,LGWR会将重做项从日志缓冲区写入重做日志当中,完成后就会通知用户进程,而Log File Sync就是等待这一过程的完成。如果等待比较明显,说明LGWR写的效率比较低,或者提交过于频繁。可以通过User Commits、User Rollback等统计信息来观察提交、回滚次数。解决方案:提高磁盘性能;使用批量提交;适当使用NOLOGGING / UNRECOVERABLE等选项。
 Wait Event Statistics
- Time Model Statistics
主要看:sql execute elapsed time、parse time elapsed、hard parse elapsed time、PL/SQL execution elapsed time、PL/SQL compilation elapsed time。
- Operating System Statistics
- Foregroud Wait Class
前台等待时间分类。
- Foreground Wait Events
Top 5等待事件。
- Backgroud Wait Events
control file parallel write:
如果等待时间比较长,说明更新所有控制文件比较慢,需要检查磁盘I/O是否存在瓶颈。可以考虑:适当减少控制文件个数;如果系统支持,使用异步I/O;将控制文件转移到I/O负担较轻的磁盘。
log file parallel write
db file sequential read
db file async I/O submit
db file parallel read
 SQL Statistics
- SQL ordered by Elapsed Time | CPU Time | User I/O Wait Time | Physical Reads (UnOptimized)
查看花费时间最多的SQL语句的执行计划。有些是递归调用产生的语句。
- SQL ordered by Gets
按照执行逻辑I/O多了来进行排序。Buffer Gets的值大并不能说明这条语句有性能问题,要和physical reads来对比,如果这两个值比较接近,那么这条语句存在问题。需要查看执行计划,看看为什么physical reads的值这么高。
另外看看Gets per Exec列,如果值太大,看看是否使用了比较差的索引,或者不合理的表连接。
· 大量的逻辑读会有较高的CPU消耗,所以当CPU消耗将近100%的时候,如果是SQL的问题,我们可以分析一下逻辑读较高的SQL(实现即时查看):
SELECT * FROM (
SELECT substr(sql_text, 1, 40) sql, buffer_gets, executions,
buffer_gets/executions “Gets/Exec”, hash_value, address
FROM v$sqlarea
WHERE buffer_gets > 0 AND executions > 0
ORDER BY buffer_gets DESC
) WHERE rownum <= 10;
- SQL ordered by Reads
查看I/O比较多的语句。
- SQL ordered by Executions
查看执行次数最多的语句。
- SQL ordered by Parse Calls
查看解析调用最多的语句。主要显示Parse和Executions的对比情况。如果Parse / Executions > 1, 说明这个语句有问题,例如没有使用绑定变量、共享池太小、cursor_sharing = exact、没有设置session_cached_cursors等。
 I/O Stats
关注Av Rd(ms)列,大部分磁盘系统都能达到14ms以下,Oracle认为超过20ms都是不必要的,如果超过1000ms,那肯定存在I/O性能瓶颈问题。还有就是Av Reads / s列。可以考虑使用分区表、ASM去均衡I/O。
 Buffer Pool Statistics (内存缓冲区)
参考一下Pool Hit、Buffer Gets、Physical Reads、Physical Writes。
 Advisory Statistics
- Instance Recovery Stats
意外宕机、执行CKPT的情况。
如果Target Redo Blks和Log Sz Redo Blks值很大,说明执行CKPT的时间很长。可以去设置执行CKPT的频率,参考Estd MTTR(s)列,设置fast_start_mttr_target参数,调整恢复所需时间的期望值。
- Buffer Pool Advisory、PGA Memory Advisor、Shared Pool Advisory、SGA Target Advisory、Streams Pool Advisory
Size Factor = 1的列是为当前值。
另外再参考一下PGA Aggr Summary、PGA Aggr Target Stats、PGA Aggr Target Histogram
 Undo Statistics
- Undo Segment Summary
 Latch Statistics
- Latch Activity
查看一下request不同Latch的次数。
 Dictionary Cache Statistics (共享池 – 数据字典缓存)和Library Cache Statistics (共享池 – 库高速缓存)
 Memory Statistics
 Resource Limit Statistics (用户CPU调用、逻辑读等)
D. ADDM
官方文档:Database Administration – Performance Tuning Guide – Automatic SQL Tuning.
自动诊断监视工具(Automatic Database Diagnostic Monitor),它可以根据AWR报告的内容,自动确定数据库可能存在的性能瓶颈,并给出调整措施和优化建议。ADDM可以发现过多硬解析 / 软解析、行级锁等待等问题。ADDM可以和SQL优化建议工具(SQL Tuning Advisor, STA)结合起来使用。
启用 / 禁用STA:
SYS@Orcl> BEGIN
dbms_auto_task_admin.enable | dbms_auto_task_admin.disable (
client_name => ‘sql tuning advisor’,
operation => NULL,
window_name => NULL
);
END;
/
创建STA任务:
SYS@Orcl> DECLARE
<task_name> varchar2(n);
<SQL_text> clob;
BEGIN
<SQL_text> := ‘<SELECT *>’ ||
‘<FROM … >’ ||
‘<WHERE … >’;
<task_name> := dbms_sqltune.create_tuning_task (
sql_text => <SQL_text>,
bind_list => sql_binds(anydata.ConvertNumber(n)),
user_name => ‘<HR>’,
scope => ‘COMPREHENSIVE’,
time_limit => 60,
task_name => <task_name>,
description => ‘ … ’
);
END;
/
配置STA:
SYS@Orcl> BEGIN
dbms_sqltune.set_tuning_task_parameter (
task_name => ‘<task_name>’
parameter => ‘TIME_LIMIT’, value => 300
);
END;
/
执行STA:
SYS@Orcl> BEGIN
dbms_sqltune.execute_tuning_task (
task_name => ‘<task_name>’
);
END;
/
查看STA状态:
SELECT status FROM user_advisor_tasks WHERE task_name = ‘’;
查看STA报告:
SET long 1000
SET longchunksize 1000
SET linesize 100
SELECT dbms_sqltune.report_tuning_task(‘<task_name>’) FROM dual;
生成ADDM报告:
SYS@Orcl> @$ORACLE_HOME/rdbms/admin/addmrpt.sql
-- 关注Summary of Findings、Action和Recommendation,还有Additional Information。
5. Findings
 使用时
· 不要使用SELECT *,因为解析器需要查询数据字典才知道“*”是什么,尽量把字段名称列出来;
· 尽量不要使用%,尤其在前面加%,这样是不会使用index的,除非建立的是reverse index;
· Filter要尽量是有效的;
· 不要连接过多的表,最好两个就够,连接4、5个表不如使用子查询;
· 尽量使用UNION ALL来代替UNION,因为UNION会给结果集排序;
· 尽量使用EXISTS来代替DISTINCT, IN:
SELECT DISTINCT <col1>, <col2>
FROM <tab1>, <tab2>
WHERE <tab1>.<col1> = <tab2>.<col1>;

SELECT <col1>, <col2>
FROM <tab1>
WHERE EXISTS (
SELECT ‘X’
FROM <tab2>
WHERE <tab1>.<col1> = <tab2>.<col1>
);
· 不要让数据库自己来进行隐式的类型转换;
· 视图的SELECT语句后面最好不要包含伪列rownum;
· 在视图外面进行ORDER BY,不要在里面做;
 设计时
· 外键必须加索引;
· 设计表的时候,尽量考虑到很有可能进行连接的列,保持他们的类型是一致的,例如不要一边是NVARCHAR2,一边是VARCHAR2;
· 做OLAP系统的时候,如果是12C,可以考虑使用IN MEMORY OPTION.
二十八、 Errors
查看报错信息:
[oracle@RedQueen ~]$ oerr <ora> <12345>
1. 故障类别
A. 语句故障
问题 解决办法
在表中输入无效的数据 与用户合作来验证并更新数据
执行操作,但权限不足 提高适当的对象或系统权限
分配空间失败 启用可恢复的空间分配,增加所有者限额,增加表空间
应用程序存在逻辑错误 与开发人员合作来更正程序错误

B. 用户进程故障
问题:
如果用户执行异常断开连接的操作、用户会话异常终止、用户遇到程序错误并终止了会话。
解决办法:
如果PMON发现某个服务器进程的用户不再连接,PMON会恢复任何实时事务;还会rollback还没提交的事务、解除任何的锁。
C. 网络故障
问题 解决办法
监听程序失败 配置备份监听程序、连接故障时转移
网络接口卡(NIC)故障 配置多个网卡
网络连接失败 配置备份网络连接

D. 用户错误
问题 解决办法
用户无意中删除或者修改了数据 回退或者使用闪回查询进行恢复
用户删除表 从回收站当中恢复表

E. 实例故障
使用SHUTDOWN ABORT、STARTUP FORCE命令、断电、硬件故障时,也会发生实例错误。实例恢复不需要用户干预,又后台进程SMON自动完成。
F. 介质故障
介质故障是指任何导致一个或多个数据库文件(数据文件、控制文件、重做日志文件)丢失或损坏的故障。
解决办法:(先还原,后恢复)
i. 从备份当中还原文件
ii. 对这个备份的文件使用日志 / 归档文件进行恢复

预防介质故障发生的方案:
做好三大文件的规划。
· 计划常规备份
· 多路复用控制文件、使用RMAN自动定期备份
· 多路复用重做日志文件组
· 保留重做日志归档的副本
(建议开启归档,但可以看情况,例如数据仓库,很少DML操作,不一定要开启;事务性操作比较多的,则需要开启)
2. 数据库没有关闭,但不让连接
[oracle@RedQueen ~]$ sqlplus / as sysdba -- ok
SYS@orcl> select status from v$instance; /* ORA-01012: not logged on */
[oracle@RedQueen ~]$ ps –ef | grep ora_ -- 有后台进程
--实例和数据库之间似乎没有连接

Solution: kill进程,使实例关闭,重新开启
[oracle@RedQueen ~]$ ps –ef | grep ora_smon_
kill -9 1234
ps -ef | grep ora_
sqlplus / as sysdba
SYS@orcl> startup
3. 监听器无服务
[oracle@RedQueen ~]$ lsnrctl start
The listener supports no services.

Solution:
/*动态监听:*/
SYS@orcl> alter system register;
[oracle@RedQueen ~]$ lsnrctl start
/*静态监听:*/
[Oracle@RedQueen ~]$ vi $ORACLE_HOME/network/admin/listener.ora
-- 注意比对<LISTENERn>和<SID_LIST_LISTENERn>
4. ORA-00205
查看数据库状态:
SYS@Orcl> SELECT status FROM v$instance;
查看警告文件:
less $ORACLE_BASE/diag/rdbms/<sid>/<sid>/trace/alert_<sid>.log
/ORA-

SYS@Orcl> ALTER DATABASE nomount;
ALTER DATABASE mount;
ALTER DATABASE open;
5. ORA-00214
启动时version过低。
Solution: 用高版本号的控制文件覆盖低版本的。
6. 没有归档,控制文件、日志丢失
Error:
SYS@Orcl> ho cp <path>/bcp.ctl <path>/re.ctl
SYS@Orcl> ALTER DATABASE open;
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
SYS@Orcl> ALTER DATABASE open resetlogs;
ORA-01194: file n needs more recovery to be consistent
ORA-01110: data file 1: ‘<path>/<data_file>.dbf’
SYS@Orcl> RECOVER DATABASE;
ORA-01610: recovery using the BACKUP CONTROLFILE option must be done
ORA-00283: recovery session canceled due to errors
SYS@Orcl> RECOVER DATABASE using backup controlfile;
ORA-00279: …
ORA-00298: suggestion: <path>/archive.arc
ORA-00280: … sequence #n
Specify log: {<RET> = suggested | filename | AUTO | CANCEL}
SYS@Orcl> exit
SYS@Orcl> SELECT group#, status FROM v$log;
SELECT member FROM v$logfile; /*path*/
Specify log:
<path>/redo.log
ORA-00326: log begins at change n, need earlier change m
ORA-00334: archived log: ‘<path>/redo.log’


Solution:
建议开启归档
SYS@Orcl> ALTER SYSTEM set “_allow_resetlogs_corruption”=true scope=spfile;
SYS@Orcl> ALTER DATABASE open resetlogs;
ORA-01113: file n needs media recovery
ORA-01110: data file 1: ‘<path>/<data_file>.dbf’
SYS@Orcl> RECOVER DATABASE;
ORA-01610: recovery using the BACKUP CONTROLFILE option must be done
ORA-00283: recovery session canceled due to errors
SYS@Orcl> RECOVER DATABASE using backup controlfile until cancel;
ORA-00279: …
ORA-00298: suggestion: <path>/archive.arc
ORA-00280: … sequence #n
Specify log: {<RET> = suggested | filename | AUTO | CANCEL}
CANCEL
ORA-01547: warning: RECOVER succeed but OPEN RESETLOGS would get error below
ORA-01194: file n needs more recovery to be consistent

ORA-01112: media recovery not started
SYS@Orcl> STARTUP FORCE
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
SYS@Orcl> ALTER DATABASE open resetlogs;
ERROR at line 1:
ORA-00603: ORACLE server session terminated by fatal error
ORA-00600: …
ORA-01092: ORACLE instance terminated. Disconnection forced
Process ID: n
Session ID: …
SYS@Orcl> exit
SYS@Orcl> sqlplus / as sysdba
SYS@Orcl> startup
Database opened.
SYS@Orcl> ALTER SYSTEM reset “_allow_resetlogs_corruption” scope=spfile sid=‘*’;
SYS@Orcl> startup force
7. 数据库还原与恢复

原理:
1. 利用备份对数据库进行还原;
2. 利用归档1 ~ n对数据库进行恢复;
3. 利用联机重做日志恢复归档n ~ DB down的部分。
建议:
1. 保证归档文件的可用性 – 打开归档;产生多份副本;
2. 保证重做日志文件的可用性 – 创建日志成员。
步骤:/* TBC */
1. Shutdown
2. Startup mount
3. Cp
4. Recover
- Apply delta Archived Log
- Apply delta Online Redo Log
5. Alter database open

0 0
原创粉丝点击