Skip to content

Oracle - 58. page

Oracle 11g OCM之表空间加密

表空间加密

  • 1.1.wallet链接
  • 1.2.表空间加密解释连接

表空间加密即对表空间里的所有数据进行自动加密,它能够保证在数据文件或者数据备份泄漏的情况下保证数据的安全性。
表空间的加密采用transparent data encryption architecture即透明数据加密结构,加密方式类似以前常见的TDE。加密的密钥再次由一个称为主密钥的密钥二次加密,主密钥存储在wallet中。加密后的表空间加密的密钥存储在数据库中的字典表中。只需要对数据表空间进行加密,临时表空间和回滚表空间并不需要加密,因为在将数据写入redo,undo,temp时候,数据库会自动进行加密。wallet无法对sys用户的对象或者数据进行加密。

加密表空间有一定的限定条件,不能对已经在使用的表空间进行加密,但是可以通过向加密表空间中利用数据泵导入数据,或使用ctas或atm把已经存在数据转储到加密表空间。官网还关于LOB方面注释:
There is no need to use LOB encryption on SECUREFILE LOBs stored in an encrypted tablespace.

使用表空间加密的步骤:

  • 1.3.创建表空间加密的主密匙存放目录(wallet目录)

[oracle@luda 23:03:32|~]mkdir $ORACLE_HOME/luda_wallets

  • 1.4.设置SQLNET.ORA文件中的ENCRYPTION_WALLET_LOCATION 参数指定使用密匙目录。

[oracle@luda 23:07:37|/oracle/product/11.2/network/admin]cat sqlnet.ora

ENCRYPTION_WALLET_LOCATION=

(SOURCE=

(METHOD=file)

(METHOD_DATA=

(DIRECTORY=/oracle/product/11.2/luda_wallets)))

[oracle@luda 23:07:40|/oracle/product/11.2/network/admin]

  • 1.5.重新启动数据库

[oracle@luda 23:09:23|/oracle/product/11.2/network/admin]sq

SQL*Plus: Release 11.2.0.1.0 Production on Tue Nov 13 23:09:25 2012

Copyright (c) 1982, 2009, Oracle.  All rights reserved.
Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup

ORACLE instance started.

Total System Global Area  422670336 bytes

Fixed Size                  1336960 bytes

Variable Size             318769536 bytes

Database Buffers           96468992 bytes

Redo Buffers                6094848 bytes

Database mounted.

Database opened.

SQL>

  • 1.6.打开wallet

SQL> ALTER SYSTEM SET ENCRYPTION KEY IDENTIFIED BY “oracle”;

System altered.

*已经打开wallet,再次打开就会报错

SQL> ALTER SYSTEM SET ENCRYPTION WALLET OPEN IDENTIFIED BY “oracle”;

ALTER SYSTEM SET ENCRYPTION WALLET OPEN IDENTIFIED BY “oracle”

*

ERROR at line 1:

ORA-28354: wallet already open
SQL>

  • 1.7. 表空加密的算法

透明的数据加密,支持标准的加密算法,包括高级加密标准(AES)和三重数据加密标准(3DES)算法,默认使用AES128:

1)AES256

2)AES192

3)AES128

4)3DES168

oracle官方解释对于加密表空间没有额外的磁盘空间开销。

  • 1.8 创建加密表空间

SQL>   create tablespace luda_ent datafile ‘/data01/ludaent01.dbf’ size 100M

2          encryption default storage(encrypt);

Tablespace created.

  • 1.9 其他加密算法操作

create tablespace luda_ent02 datafile ‘/data01/ludaent02_1.dbf’ size 20M

encryption using ‘3DES168’ default storage(encrypt);

  • 2.0查询表空间的加密信息

SQL> SELECT t.name, e.encryptionalg algorithm  FROM  v$tablespace t, v$encrypted_tablespaces e WHERE t.ts# = e.ts#;

NAME                           ALGORIT

—————————— ——-

LUDA_ENT                       AES128

LUDA_ENT02                     3DES168

  • 2.1.关闭加密表空间

 

drop tablespace luda_ent including contents and datafiles;

drop tablespace luda_ent02 including contents and datafiles;

col WRL_PARAMETER for a40

col status for a10

select * from v$encryption_wallet;

WRL_TYPE             WRL_PARAMETER                            STATUS

——————– —————————————- ———-

file                 /oracle/product/11.2/luda_wallets        OPEN

  • 2.2.关闭wallet

SQL> alter system set encryption wallet close identified by “oracle”;

System altered.

*关闭wallet后,对已经加密过的数据将无法查询。

Oracle 11g OCM复习项目列表(更新中)

标注:

字体蓝色:表示已经写完,正在整理发布

字体黑色 :表示正在酝酿怎么写~:)

 

1.数据库,备份恢复管理器,GC,网络配置和管理

 

  1. 服务端的网络配置
  2. 客户端的网络配置
  3. 加密表空间的管理
  4. 使用NFS文件系统创建表空间
  5. 管理使用自动诊断信息库(ADR
  6. 创建数据库冷备份
  7. 管理用户帐户和使用敏感密码
  8. 使用Opatch安装补丁
  9. GCAgent的安装和配置
  10. 创建和设置恢复目录
  11. 配置RMAN
  12. 执行数据文件的冗余备份
  13. 创建归档备份

 

2.数据和数据仓库管理

 

  1. 恢复物化视图的快速刷新或查询重写
  2. 传输表空间
  3. 星型转换
  4. 设置并行查询操作
  5. 使用和访问SecurefilesLOBS
  6. 创建分区表
  7. 设置闪回归档
  8. 使用Oracle流捕获和传播表中发生变化的的数据

 

3.Dataguard

 

  1. 创建物理Standby并使用实时模式
  2. 配置快速增量备份,以减少开销
  3. 配置Observer
  4. DG的切换和回切
  5. 将备库转换成快照备库
  6. 配置归档日志删除策略

 

4.性能管理

 

  1. 配置的资源管理器来控制I / O的数量活动会话的数量
  2. 使用高速缓存查询结果
  3. 使用多列统计信息
  4. 使用索引分区
  5. 使用SQL Tuning Advisor
  6. 使用SQLAccess Advisor
  7. 配置基线模板
  8. 使用SQL执行计划管理特性
  9. 数据库重放

oracle 9i的一个小故障

客户在中午11点20分打电话非常紧急的说到,李工,快看看数据库,不知道为什么客户端登录不上去,看了数据库服务都很闲
第一反应就是数据库可能陷入死循环了,骂了一声,最近没少碰到数据库死循环的。
远程直接登录sqlplus~


[oracle@node1 21:56:26|~]sqlplus '/as sysdba'

SQL*Plus: Release 9.2.0.7.0 - Production on Fri May 11 ****** 2012

Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 9.2.0.7.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL&

发现数据库可以登录,想想是不是监听网络有问题,逐测试一下服务名

[oracle@node1 22:11:52|/oracle/product/1020/network/admin]tnsping ecgolo

TNS Ping Utility for Linux: Version 9.2.0.7.0 - Production on 11-MAY-2012 ******

Copyright (c) 1997, 2004, Oracle. All rights reserved.

Used parameter files:

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = node1)(PORT = 1521)) (CONNECT_DATA = (server = dedicated) (SID_NAME=ecgolo)))
OK (240 msec)

tnsping验证oracle的网络设置也没问题,那到底是哪里有问题?

测试一拔
sqlplus test/test@ecgolo

[oracle@node1 21:56:26|~]sqlplus test/test@egcolo

SQL*Plus: Release 9.2.0.7.0 - Production on Fri May 11 ******** 2012

Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

发现登录时候挂在这里无法登录进实例,可以确实是oracle引起的问题,尝试关闭数据库,数据库关闭过程卡住,ok既然确定数据库有问题先看告警,结果发现
Fri May 11 11:28:32 2012
>>> WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK! pid=6
Fri May 11 11:50:56 2012
Shutting down instance: further logons disabled
Shutting down instance (immediate)
License high water mark = 342

从上面可以看到在关闭数据库shudown immediate命令已经执行,但是同事也有相关的告警

>>> WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK! pid=6

这个告警不可忽略,如果告警中出现row cache 队列锁那么往往造成的问题都是不可忽视的哦,那么这里的话出现了这个错误
很多人联想到的都是row cache,数据字典池出问题了,没错,我们的知识往往能把我们很快的定位到相关的地方,但是这里
我要说的是,判断一个故障…知识大多只能起到辅助作用,由于此库是此集团全国几十家五星酒店的业务数据库,一旦hang住
所有的入住手续既无法办理,所以在碰到这个故障时候我首先的态度还是以恢复业务为目的,发现这个告警可以再对近期的告警
进行排查,一般此告警都有伴随性的提示,结果真的发现如下:
Fri May 11 06:31:08 2012
Database Characterset is ZHS16GBK
replication_dependency_tracking turned off (no async multimaster replication found)
Completed: ALTER DATABASE OPEN
Fri May 11 09:44:36 2012
Thread 1 advanced to log sequence 79384
Current log# 1 seq# 79384 mem# 0: /oadb/oradata/ecology/redo01.log
Fri May 11 09:45:35 2012
Thread 1 advanced to log sequence 79385
Current log# 3 seq# 79385 mem# 0: /oadb/oradata/ecology/redo03.log
Fri May 11 09:46:41 2012
ORACLE Instance ecology - Can not allocate log, archival required
Fri May 11 09:46:41 2012
ARCH: Connecting to console port...
Thread 1 cannot allocate new log, sequence 79386
All online logs needed archivinga
Current log# 3 seq# 79385 mem# 0: /oadb/oradata/ecology/redo03.log

我想此时问题有点头绪了,客户重启了一次数据库,因为正在搬迁机房,因为是9i的数据库,在重启的过程中并没有修改log_archive_start为
TRUE,造成数据库在启动后运行一段时间之后就无法运行了,因为在线日志组都已经写满了,而且arch进程并不会自动去归档在线日志组,当切
换到一个轮回后就hang住了,具体内部的切换的涉及到的sql修改的内部表这里就不做描述了,我们直接来验证是否如我所判断的一样:

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_archive_start boolean FALSE
SQL>

果然不出大头所料,修改之,并强制关闭数据库再次启动,尝试切换归档日志,成功。

ARC1: Evaluating archive log 2 thread 1 sequence 79386
ARC1: Beginning to archive log 2 thread 1 sequence 79386
Creating archive destination LOG_ARCHIVE_DEST_1: '/oadbarc/1_79386.dbf'
Fri May 11 12:08:30 2012
Successfully onlined Undo Tablespace 1.
Fri May 11 12:08:30 2012
SMON: enabling tx recovery
Fri May 11 12:08:30 2012
Database Characterset is ZHS16GBK
replication_dependency_tracking turned off (no async multimaster replication found)
Completed: alter database open
Fri May 11 12:08:32 2012
ARC0: Completed archiving log 3 thread 1 sequence 79385
Fri May 11 12:08:32 2012
ARC1: Completed archiving log 2 thread 1 sequence 79386
Fri May 11 12:08:32 2012
SMON: Parallel transaction recovery tried
Fri May 11 12:08:40 2012
Thread 1 advanced to log sequence 79388
Current log# 3 seq# 79388 mem# 0: /oadb/oradata/ecology/redo03.log
Fri May 11 12:08:40 2012
ARC0: Evaluating archive log 1 thread 1 sequence 79387
ARC0: Beginning to archive log 1 thread 1 sequence 79387
Creating archive destination LOG_ARCHIVE_DEST_1: '/oadbarc/1_79387.dbf'
ARC0: Completed archiving log 1 thread 1 sequence 79387
Fri May 11 12:08:57 2012
Thread 1 advanced to log sequence 79389
Current log# 2 seq# 79389 mem# 0: /oadb/oradata/ecology/redo02.log
Fri May 11 12:08:57 2012
ARC0: Evaluating archive log 3 thread 1 sequence 79388
ARC0: Beginning to archive log 3 thread 1 sequence 79388
Creating archive destination LOG_ARCHIVE_DEST_1: '/oadbarc/1_79388.dbf'
ARC0: Completed archiving log 3 thread 1 sequence 79388

服务问题

昨天碰到个有趣的事,客户在一台服务器上删除15g的财务数据以便准备省审计厅的检查,下午三点打电话过来说他的台式电脑上的oracle一旦开启整个磁盘灯疯狂的闪…整个xp处于崩溃状态…好吧,我在车上…让公司的同事先远程处理,公司的电工还有坤哥忙活了四个多小时客户宣布…终止远程,期间同事打电话告诉我表示对客户的无赖…客户打电话表示对支持的意见…发现两个同事都没有将联系方式及时告知客户,而客户在时间紧迫的情况下也没有告知同事此次问题前的一些操作情况。从中协调的问题很明显,在此类问题处理中必须保持好和客户的沟通,要先了解事发前后的状况,并及时通报处理情况缓解客户紧张的心理。

ITL争用阻塞与ITL死锁

ITL(Interested Transaction List)是Oracle数据块内部的一个组成部分,用来记录该块所有发生的事务,一个itl可以看作是一个记录,在一个时间,可以记录一个事务(包括提交或者未提交事务)。当然,如果这个事务已经提交,那么这个itl的位置就可以被反复使用了,因为itl类似记录,所以,有的时候也叫itl槽位。

如果一个事务一直没有提交,那么,这个事务将一直占用一个itl槽位,itl里面记录了事务信息,回滚段的入口,事务类型等等。如果这个事务已经提交,那么,itl槽位中还保存的有这个事务提交时候的SCN号。如dump一个块,就可以看到itl信息:
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0006.002.0000158e 0x0080104d.00a1.6e –U- 734 fsc 0x0000.6c9deff0
0x02 0x0000.000.00000000 0x00000000.0000.00 —- 0 fsc 0x0000.00000000

对于已经提交的事务,itl槽位最好不要马上被覆盖,因为一致性读可能会用到这个信息,一致性读的时候,可能需要从这里获得回滚段的入口,并从回滚段中获得一致性读。

itl的个数,受参数initrans控制,最大的itl个数,受maxtrans控制,在一个块内部,默认分配了2个或3个itl的个数,如果这个块内还有空闲空间,那么Oracle是可以利用这些空闲空间并再分配itl。如果没有了空闲空间,那么,这个块因为不能分配新的itl,所以就可能发生itl等待。

如果在并发量特别大的系统中,最好分配足够的itl个数,其实它并浪费不了太多的空间,或者,设置足够的pctfree,保证itl能扩展,但是pctfree有可能是被行数据给消耗掉的,如update,所以,也有可能导致块内部的空间不够而导致itl等待。

以下是一个ITL等待的例子:
Luda@10gR2>create table test(a int) pctfree 0 initrans 1;
Table created.

我们这里指定pctfree为0,initrans为1,就是为了更观察到itl的真实等待情况,那么,现在,我们给这些块内插入数据,把块填满,让它不能有空间分配。
Luda@10gR2>begin
2 for i in 1..2000 loop
3 insert into test values(i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
Luda@10gR2>commit;
Commit complete.

我们再检查数据填充的情况:
Luda@10gR2>select f,b,count(*) from (
2 select dbms_rowid.rowid_relative_fno(rowid) f,
3 dbms_rowid.rowid_block_number(rowid) b
4 from test) group by f,b;

F B COUNT(*)
———- ———- ———-
1 29690 734
1 29691 734
1 29692 532

可以发现,这2000条数据分布在3个块内部,其中有2个块添满了,一个块是半满的。我们dump一个满的块,可以看到itl信息:
Luda@10gR2>alter system dump datafile 1 block 29690;

回到os,在udump目录下,检查跟踪文件,可以看到如下的信息
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0006.002.0000158e 0x0080104d.00a1.6e –U- 734 fsc 0x0000.6c9deff0
0x02 0x0000.000.00000000 0x00000000.0000.00 —- 0 fsc 0x0000.00000000

发现,采用如上参数创建的表,块内部默认有2个itl槽位,如果这里不指定initrans 1,默认是有3个itl槽位的。

因为只有2个ITL槽位,我们可以用三个会话来模拟等待:

会话1,我们更新这个块内部的第一行:
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;
1 row updated.

会话2,我们更新这个块内部的第2行:
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=2;
1 row updated.

会话3(SID=153),我们更新这个块内部的第三行,发现被阻塞:
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;

可以看到,会话被阻塞

观察这个时候的等待事件,我们可以发现是ITL等待:
Luda@10gR2>select EVENT from v$session_wait where sid=153
EVENT
—————————-
enq: TX – allocate ITL entry

因为该块只有2个itl槽位,而现在发生了3个事务,而且,因为该块被数据添满,根本没有剩余的空间来分配新的itl,所以发生了等待。如果我们这个实验发生在半满的块29692上面,就发现进程3不会被阻塞,因为这里有足够的空间可以分配新的itl。

3、ITL死锁

那么,理解了itl的阻塞,我们也就可以分析itl的死锁了,因为有阻塞,一般就能发生死锁。还是以上的表,因为有2个itl槽位,我们需要拿2个满的数据块,4个进程来模拟itl死锁:

会话1
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;
1 row updated.

会话2
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=2;
1 row updated.

会话3
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;
1 row updated.

会话4
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=2;
1 row updated.

以上4个进程把2个不同块的4个itl槽位给消耗光了,现在的情况,就是让他们互相锁住,达成死锁条件,回到会话1,更新块2,注意,以上4个操作,包括以下的操作,更新的根本不是同一行数据,主要是为了防止出现的是TX等待。
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;

发现被阻塞

那我们在会话3,更新块1,当然,也不是同一行
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;

被阻塞

注意,如果是9i,在这里就报死锁了,在进程1,我们可以看到
Luda@9iR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;
update test set a=a
where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource

但是,在10g里面,这个时候,死锁是不会发生的,因为这里的进程1还可以等待进程4释放资源,进程3还可以等待进程2释放资源,只要进程2与进程4释放了资源,整个环境又活了,那么我们需要把这两个进程也塞住。

会话2,注意,我们也不是更新的同一行数据
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=4;

被阻塞

还有最后一个进程,进程4,我们也不更新同一行数据
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=4;

虽然,以上的每个更新语句,更新的都不是同一个数据行,但是,的确,所有的进程都被阻塞住了,那么,死锁的条件也达到了,马上,我们可以看到,进程1出现提示,死锁:
Luda@10gR2>update test set a=a
2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;

update test set a=a
where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource

4、ITL等待与死锁的避免

为了避免以上的情况发生,我们一定要注意在高并发环境下的表中,正确的设置itl个数,如4个,8个等等,保证该块有足够的itl槽位,保证事务能顺利的进行,而没有itl的等待。关于itl的等待,在statspack的段报告中,也能很明显的看到:
Top 5 ITL Waits per Segment for DB: TEST Instance: test Snaps: 13013 -13014
-> End Segment ITL Waits Threshold: 100

Subobject Obj. ITL
Owner Tablespace Object Name Name Type Waits %Total
———- ———- ——————– ———- —– ———— ——-
TEST TBS_EL_IND IDX_LLORDER_ORDERID INDEX 3 75.00
TEST TBS_INDEX2 IDX_AUC_FEED_FDATE INDEX 1 25.00

如果出现的频率很小,象上面的情况,一般可以不用干预,但是,如果waits很多,则表示这个对象有很严重的itl争用情况,需要增加itl个数。
如果想增加initrans个数,参数可以动态修改,但是,只是针对以后的新块起效,以前的块如果想生效,需要在新参数下,重整表数据,如重建该表,或者move该表。