2. 表分区或子分区的在线迁移
在Oracle 12c R1中迁移表分区或子分区到不同的表空间不再需要复杂的过程。与之前版本中未分区表进行在线迁移类似,表分区或子分区可以在线或是离线迁移至一个不同的表空间。当指定了ONLINE语句,所有的DML操作可以在没有任何中断的情况下,在参与这一过程的分区或子分区上执行。与此相反,分区或子分区迁移如果是在离线情况下进行的,DML操作是不被允许的。
示例:
1 | SQL> ALTER TABLE table_name MOVE PARTITION|SUBPARTITION partition_name TO tablespace tablespace_name; |
2 | SQL> ALTER TABLE table_name MOVE PARTITION|SUBPARTITION partition_name TO tablespace tablespace_name UPDATE INDEXES ONLINE; |
第一个示例是用来在离线状况下将一个表分区或子分区迁移至一个新的表空间。第二个示例是在线迁移表分区或子分区并维护表上任何本地或全局的索引。此外,当使用ONLINE语句时,DML操作是不会中断的。
重要提示::
UPDATE INDEXES语句可以避免出现表中任何本地或全局索引无法使用的情况。
表的在线迁移限制也适用于此。
引入加锁机制来完成这一过程,当然它也会导致性能下降并会产生大量的redo,这取于分区和子分区的大小。
3. 不可见字段
在Oracle 11g R1中,Oracle以不可见索引和虚拟字段的形式引入了一些不错的增强特性。继承前者并发扬光大,Oracle 12c R1中引入了不可见字段思想。在之前的版本中,为了隐藏重要的数据字段以避免在通用查询中显示,我们往往会创建一个视图来隐藏所需信息或应用某些安全条件。
在12c R1中,你可以在表中创建不可见字段。当一个字段定义为不可见时,这一字段就不会出现在通用查询中,除非在SQL语句或条件中有显式的提及这一字段,或是在表定义中有DESCRIBED。要添加或是修改一个不可见字段是非常容易的,反之亦然。
1 | SQL> CREATE TABLE emp (eno number(6), ename name varchar2(40), sal number(9) INVISIBLE); |
2 | SQL> ALTER TABLE emp MODIFY (sal visible); |
你必须在INSERT语句中显式提及不可见字段名以将不可见字段插入到数据库中。虚拟字段和分区字段同样也可以定义为不可见类型。但临时表,外部表和集群表并不支持不可见字段。
4. 相同字段上的多重索引
在Oracle 12c R1之前,一个字段是无法以任何形式拥有多个索引的。或许有人会想知道为什么通常一个字段需要有多重索引,事实上需要多重索引的字段或字段集合是很多的。在12c R1中,只要索引类型的形式不同,一个字段就可以包含在一个B-tree索引中,同样也可以包含在Bitmap索引中。注意,只有一种类型的索引是在给定时间可用的。
5. DDL日志
在之前的版本中没有可选方法来对DDL操作进行日志记录。而在12c R1中,你现在可以将DDL操作写入xml和日志文件中。这对于了解谁在什么时间执行了create或drop命令是十分有用的。要开启这一功能必须对ENABLE_DDL_LOGGING 初始参数加以配置。这一参数可以在数据库或会话级加以设置。当此参数为启用状态,所有的DDL命令会记录在$ORACLE_BASE/diag/rdbms/DBNAME/log|ddl 路径下的xml和日志文件中。一个xml中包含DDL命令,IP地址,时间戳等信息。这可以帮助确定在什么时候对用户或表进行了删除亦或是一条DDL语句在何时触发。
开启DDL日志功能
1 | SQL> ALTER SYSTEM|SESSION SET ENABLE_DDL_LOGGING=TRUE; |
以下的DDL语句可能会记录在xml或日志文件中:
1 | CREATE|ALTER|DROP|TRUNCATE TABLE |
2 | DROP USER |
3 | CREATE|ALTER|DROP PACKAGE|FUNCTION|VIEW|SYNONYM|SEQUENCE |
6. 临时undo
每个Oracle数据库包含一组与系统相关的表空间,例如SYSTEM,SYSAUX,UNDO & TEMP,并且它们在Oracle数据库中每个都用于不同的目的。在Oracle 12c R1之前,undo记录是由临时表产生并存储在undo表空间中的,这更类似于一个通用或持久的表撤销记录。然而,由于在12c R1中引入了临时undo功能,那些临时undo记录现在就可以存储在临时表中,而不是存储在undo表空间中。临时undo的主要好处在于:由于信息不会写入undo日志,undo表空间的开销得以减少并且产生的undo数据会更少。而对于在会话级还是数据库级开启临时undo功能你是可以灵活选择的。
启用临时undo功能
要使用这一新功能,需要做以下设置:
兼容性参数必须设置为12.0.0或更高
启用 TEMP_UNDO_ENABLED 初始化参数
由于临时undo记录现在是存储在一个临时表空间中的,你需要有足够的空间来创建这一临时表空间
对于会话级,你可以使用:ALTER SYSTEM SET TEMP_UNDO_ENABLE=TRUE;
查询临时undo信息
以下所列的字典视图是用来查看或查询临时undo数据相关统计信息的:
1 | V$TEMPUNDOSTAT |
2 | DBA_HIST_UNDOSTAT |
3 | V$UNDOSTAT |
要禁用此功能,你只需做以下设置:
1 | SQL> ALTER SYSTEM|SESSION SET TEMP_UNDO_ENABLED=FALSE; |
7. 备份特定用户特权
在11g R2中,引入了SYSASM特权来执行ASM的特定操作。同样地,在12c中引入了SYSBACKUP特权用来在 RMAN中执行备份和恢复命令。因此,你可以在数据库中创建一个本地用户并在不授予其SYSDBA权限的情况下,通过授予SYSBACKUP权限让其能够在RMAN中执行备份和恢复相关的任务。
1 | $ ./rman target "username/password as SYSBACKUP" |
8. 如何在RMAN中执行SQL语句
在12c中,你可以在不需要SQL前缀的情况下在RMAN中执行任何SQL和PL/SQL命令,即你可以从RMAN直接执行任何SQL和PL/SQL命令。如下便是在RMAN中执行SQL语句的示例
1 | RMAN> SELECT username,machine FROM v$session; |
2 | RMAN> ALTER TABLESPACE users ADD DATAFILE SIZE 121m; |
9. RMAN中的表恢复和分区恢复
Oracle数据库备份主要分为两类:逻辑和物理备份。每种备份类型都有其自身的优缺点。在之前的版本中,利用现有物理备份来恢复表或分区是不可行的。为了恢复特定对象,逻辑备份是必需的。对于12c R1,你可以在发生drop或truncate的情况下从RMAN备份将一个特定的表或分区恢复到某个时间点或SCN。
当通过RMAN发起一个表或分区恢复时,大概流程是这样的:
确定要恢复表或分区所需的备份集
在恢复表或分区的过程中,一个辅助数据库会临时设置为某个时间点利用数据泵将所需表或分区导出到一个dumpfile
你可以从源数据库导入表或分区(可选)
在恢复过程中进行重命名操作
以下是一个通过RMAN对表进行时间点恢复的示例(确保你已经对稍早的数据库进行了完整备份):
1 | RMAN> connect target "username/password as SYSBACKUP"; |
2 | RMAN> RECOVER TABLE username.tablename UNTIL TIME 'TIMESTAMP…' |
3 | AUXILIARY DESTINATION '/u01/tablerecovery' |
4 | DATAPUMP DESTINATION '/u01/dpump' |
5 | DUMP FILE 'tablename.dmp' |
6 | NOTABLEIMPORT -- this option avoids importing the table automatically.(此选项避免自动导入表) |
7 | REMAP TABLE 'username.tablename': 'username.new_table_name'; -- can rename table with this option.(此选项可以对表重命名) |
重要提示::
确保对于辅助数据库在/u01文件系统下有足够的可用空间,同时对数据泵文件也有同样保证
必须要存在一份完整的数据库备份,或者至少是要有SYSTEM相关的表空间备份
以下是在RMAN中应用表或分区恢复的限制和约束:
SYS用户表或分区无法恢复
存储于SYSAUX和SYSTEM表空间下的表和分区无法恢复
当REMAP选项用来恢复的表包含NOT NULL约束时,恢复此表是不可行的
10. 限制PGA的大小
在Oracle 12c R1之前,没有选项可以用来限制和控制PGA的大小。虽然你设置某个大小为PGA_AGGREGATE_TARGET 的初始参数,Oracle会根据工作负载和需求来动态地增大或减小PGA的大小。而在12c中,你可以通过开启自动PGA管理来对PGA设定硬性限制,这需要对PGA_AGGREGATE_LIMIT 参数进行设置。因此,你现在可以通过设置新的参数来对PGA设定硬性限制以避免过度使用PGA。
1 | SQL> ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=2G; |
2 | SQL> ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=0; --disables the hard limit |
重要提示::
当超过了当前PGA的限制,Oracle会自动终止/中止会话或进程以保持最合适的PGA内存。
11. 对表分区维护的增强
我解释了如何在线或是离线状态下迁移一个表分区或子分区到另一个不同的表空间。在本文中,主要介绍表分区其他方面的改进。
添加多个新分区
在Oracle 12c R1之前,一次只可能添加一个新分区到一个已存在的分区表。要添加一个以上的新分区,需要对每个新分区都单独执行一次ALTER TABLE ADD PARTITION语句。而Oracle 12c只需要使用一条单独的ALTER TABLE ADD PARTITION 命令就可以添加多个新分区,这增加了数据库灵活性。以下示例说明了如何添加多个新分区到已存在的分区表:
1 | SQL> CREATE TABLE emp_part |
2 | (eno number(8), ename varchar2(40), sal number (6)) |
3 | PARTITION BY RANGE (sal) |
4 | (PARTITION p1 VALUES LESS THAN (10000), |
5 | PARTITION p2 VALUES LESS THAN (20000), |
6 | PARTITION p3 VALUES LESS THAN (30000) |
7 | ); |
添加两个新分区:
1 | SQL> ALTER TABLE emp_part ADD PARTITION |
2 | PARTITION p4 VALUES LESS THAN (35000), |
3 | PARTITION p5 VALUES LESS THAN (40000); |
同样,只要MAXVALUE分区不存在,你就可以添加多个新分区到一个列表和系统分区表。
如何删除和截断多个分区/子分区
作为数据维护的一部分,DBA通常会在一个分区表上进行删除或截断分区的维护任务。在12c R1之前,对于一个已存在的分区表一次只可能删除或截断一个分区。而对于Oracle 12c, 可以用单条ALTER TABLE table_name {DROP|TRUNCATE} PARTITIONS命令来撤销或合并多个分区和子分区。
下例说明了如何在一个已存在分区表上删除或截断多个分区:
1 | SQL> ALTER TABLE emp_part DROP PARTITIONS p4,p5; |
2 | SQL> ALTER TABLE emp_part TRUNCATE PARTITONS p4,p5; |
要保持索引更新,使用UPDATE INDEXES或UPDATE GLOBAL INDEXES语句,如下所示:
1 | SQL> ALTER TABLE emp_part DROP PARTITIONS p4,p5 UPDATE GLOBAL INDEXES; |
2 | SQL> ALTER TABLE emp_part TRUNCATE PARTITIONS p4,p5 UPDATE GLOBAL INDEXES; |
如果你在不使用UPDATE GLOBAL INDEXES 语句的情况下删除或截断一个分区,你可以在USER_INDEXES或USER_IND_PARTITIONS 字典视图下查询ORPHANED_ENTRIES 字段以找出是否有索引包含任何的过期条目。
将单个分区分割为多个新分区
在12c中新增强的SPLIT PARTITION 语句可以让你只使用一个单独命令将一个特定分区或子分区分割为多个新分区。下例说明了如何将一个分区分割为多个新分区:
01 | SQL> CREATE TABLE emp_part |
02 | (eno number(8), ename varchar2(40), sal number (6)) |
03 | PARTITION BY RANGE (sal) |
04 | (PARTITION p1 VALUES LESS THAN (10000), |
05 | PARTITION p2 VALUES LESS THAN (20000), |
06 | PARTITION p_max (MAXVALUE) |
07 | ); |
08 | SQL> ALTER TABLE emp_part SPLIT PARTITION p_max INTO |
09 | (PARTITION p3 VALUES LESS THAN (25000), |
10 | PARTITION p4 VALUES LESS THAN (30000), PARTITION p_max); |
将多个分区合并为一个分区
你可以使用单条ALTER TBALE MERGE PARTITIONS 语句将多个分区合并为一个单独分区:
01 | SQL> CREATE TABLE emp_part |
02 | (eno number(8), ename varchar2(40), sal number (6)) |
03 | PARTITION BY RANGE (sal) |
04 | (PARTITION p1 VALUES LESS THAN (10000), |
05 | PARTITION p2 VALUES LESS THAN (20000), |
06 | PARTITION p3 VALUES LESS THAN (30000), |
07 | PARTITION p4 VALUES LESS THAN (40000), |
08 | PARTITION p5 VALUES LESS THAN (50000), |
09 | PARTITION p_max (MAXVALUE) |
10 | ); |
11 | SQL> ALTER TABLE emp_part MERGE PARTITIONS p3,p4,p5 INTO PARTITION p_merge; |
如果分区范围形成序列,你可以使用如下示例:
1 | SQL> ALTER TABLE emp_part MERGE PARTITIONS p3 TO p5 INTO PARTITION p_merge; |
12. 数据库升级改进
每当一个新的Oracle版本发布,DBA所要面临的挑战就是升级过程。该部分我将介绍12c中引入的针对升级的两个改进。
预升级脚本
在12c R1中,原有的utlu[121]s.sql 脚本由一个大为改善的预升级信息脚本preupgrd.sql所取代。除了预升级检查验证,此脚本还能以修复脚本的形式解决在升级过程前后出现的各种问题。
可以对产生的修复脚本加以执行来解决不同级别的问题,例如,预升级和升级后的问题。当手动升级数据库时,脚本必须在实际升级过程初始化之前加以手动执行。然而,当使用DBUA工具来进行数据库升级时,它会将预升级脚本作为升级过程的一部分加以自动执行,而且会提示你去执行修复脚本以防止报错。
如何执行脚本:
1 | SQL> @$ORACLE_12GHOME/rdbms/admin/preupgrd.sql |
以上脚本会产生一份日志文件以及一个[pre/post]upgrade_fixup.sql 脚本。所有这些文件都位于$ORACLE_BASE/cfgtoollogs 目录下。在你继续真正的升级过程之前,你应该浏览日志文件中所提到的建议并执行脚本以修复问题。
注意:你要确保将preupgrd.sql和utluppkg.sql 脚本从12c Oracle的目录home/rdbms/admin directory拷贝至当前的Oracle的database/rdbms/admin路径。
并行升级功能
数据库升级时间的长短取决于数据库上所配置的组件数量,而不是数据库的大小。在之前的版本中,我们是无法并行运行升级程序,从而快速完成整个升级过程的。
在12c R1中,原有的catupgrd.sql 脚本由catctl.pl 脚本(并行升级功能)替代,现在我们可以采用并行模式运行升级程序了。
以下流程说明了如何初始化并行升级功能(3个过程);你需要在升级模式下在启动数据库后运行这一脚本
1 | cd $ORACLE_12_HOME/perl/bin |
2 | $ ./perl catctl.pl –n 3 -catupgrd.sql |
以上两个步骤需要在手动升级数据库时运行。而DBUA也继承了这两个新变化。
13. 通过网络恢复数据文件
在12c R1中另一个重要的增强是,你现在可以在主数据库和备用数据库之间用一个服务名重新获得或恢复数据文件、控制文件、参数文件、表空间或整个数据库。这对于同步主数据库和备用数据库极为有用。
当主数据库和备用数据库之间存在相当大的差异时,你不再需要复杂的前滚流程来填补它们之间的差异。RMAN能够通过网络执行备用恢复以进行增量备份,并且可以将它们应用到物理备用数据库。你可以用服务名直接将所需数据文件从备用点拷贝至主站,这是为了防止主数据库上数据文件、表空间的丢失,或是没有真正从备份集恢复数据文件。
以下流程演示了如何用此新功能执行一个前滚来对备用数据库和主数据库进行同步:
在物理备用数据库上:
1 | ./rman target "username/password@standby_db_tns as SYSBACKUP" |
2 | RMAN> RECOVER DATABASE FROM SERVICE primary_db_tns USING COMPRESSED BACKUPSET; |
以上示例使用备用数据库上定义的primary_db_tns 连接字符串连接到主数据库,然后执行了一个增量备份,再将这些增量备份传输至备用目的地,接着将应用这些文件到备用数据库来进行同步。然而,需要确保已经对primary_db_tns 进行了配置,即在备份数据库端将其指向主数据库。
在以下示例中,我将演示一个场景通过从备用数据库获取数据文件来恢复主数据库上丢失的数据文件:
在主数据库上:
1 | ./rman target "username/password@primary_db_tns as SYSBACKUP" |
2 | RMAN> RESTORE DATAFILE ‘+DG_DISKGROUP/DBANME/DATAFILE/filename’FROM SERVICE standby_db_tns; |
14. 对Data Pump的增强
Data Pump版本有了不少有用的改进,例如在导出时将视图转换为表,以及在导入时关闭日志记录等。
关闭redo日志的生成
Data Pump中引入了新的TRANSFORM选项,这对于对象在导入期间提供了关闭重做生成的灵活性。当为TRANSFORM选项指定了DISABLE_ARCHIVE_LOGGING 值,那么在整个导入期间,重做生成就会处于关闭状态。这一功能在导入大型表时缓解了压力,并且减少了过度的redo产生,从而加快了导入。这一属性还可应用到表以及索引。以下示例演示了这一功能:
1 | $ ./impdp directory=dpump dumpfile=abcd.dmp logfile=abcd.log TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y |
将视图转换为表
这是Data Pump中另外一个改进。有了VIEWS_AS_TABLES 选项,你就可以将视图数据载入表中。以下示例演示了如何在导出过程中将视图数据载入到表中:
1 | $ ./expdp directory=dpump dumpfile=abcd.dmp logfile=abcd.log views_as_tables=my_view:my_table |
15. 实时自动数据诊断监视器 (ADDM) 分析
通过使用诸如AWR、ASH以及ADDM之类的自动诊断工具来分析数据库的健康状况,是每个DBA日程工作的一部分。尽管每种工具都可以在多个层面衡量数据库的整体健康状况和性能,但没有哪个工具可以在数据库反应迟钝或是完全挂起的时候使用。
当数据库反应迟钝或是挂起状态时,而且你已经配置了Oracle 企业管理器 12c的云控制,你就可以对严重的性能问题进行诊断。这对于你了解当前数据库发生了什么状况有很大帮助,而且还能够对此问题给出解决方案。
以下步骤演示了如何在Oracle 企业管理器 12c上分析数据库状态:
在访问数据库访问主页面从Performance菜单选择Emergency Monitoring 选项。这会显示挂起分析表中排名靠前的阻止会话。
在Performance菜单选择Real-Time ADDM 选项来执行实时ADDM分析。
在收集了性能数据后,点击Findings标签以获得所有结果的交互总结。
16. 同时在多个表上收集统计数据
在之前的Oracle数据库版本中,当你执行一个DBMS_STATS 程序来收集表、索引、模式或者数据库级别的统计数据时,Oracle习惯于一次一个表的收集统计数据。如果表很大,那么推荐你采用并行方式。在12c R1中,你现在可以同时在多个表、分区以及子分区上收集统计数据。在你开始使用它之前,你必须对数据库进行以下设置以开启此功能:
1 | SQL> ALTER SYSTEM SET RESOURCE_MANAGER_PLAN='DEFAULT_MAIN'; |
2 | SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=4; |
3 | SQL> EXEC DBMS_STATS.SET_GLOBAL_PREFS('CONCURRENT', 'ALL'); |
4 | SQL> EXEC DBMS_STATS.GATHER_SCHEMA_STATS('SCOTT'); |