初始化参数DB_BLOCK_CHECKING控制Oracle如何全面检查读写的每个数据块的完整性。启用的检查界别是环境中的故障承受级别(通常很低)与连续检查块所需的开销折中的结果。在11g中db_block_checking参数有了更多的选项,以满足不等的块检验粒度:
SQL> alter system set db_block_checking=AA; alter system set db_block_checking=AA * ERROR at line 1: ORA-00096: invalid value AA for parameter db_block_checking, must be from among FULL, TRUE, MEDIUM, LOW, OFF, FALSE /* 可选的有 OFF=FALSE,FULL=TRUE以及MEDIUM和LOW */
不同的DB_BLOCK_CHECKING选项对应不同的检查粒度:
- OFF或FALSE 不执行任何检查块的操作
- LOW 在内存中更改块或从磁盘中读取块后对块进行基本检查,其中包括RAC环境中在实例间传输块的情形
- MEDIUM 包括所有LOW检查,另加检查所有非IOT(索引组织表)块
- FULL或TRUE 包括所有LOW和MEDIUM检查,另加检查索引块
在客户愿意承担性能开销的前提下,Oracle建议使用FULL值。默认值是OFF,但仍始终启用针对SYSTEM表空间的FULL块检查功能(受到隐式参数_db_always_check_system_ts的控制,默认为TRUE)。通常认为块检查开销的范围在1%~10%之间,在OLTP环境中更接近于10%。
以下为Oracle GCS对块检查性能损耗的描述:
Oracle checks a block by going through the data in the block, making sure it is logically self-consistent. Block checking can often prevent memory and data corruption. Block checking typically causes 1% to 10% overhead, depending on workload and the parameter value. The more updates or inserts in a workload, the more expensive it is to turn on block checking. You should set DB_BLOCK_CHECKING to FULL if the performance overhead is acceptable
- full – see above depending on updates and inserts and how well the database is tuned it can be costly 10%+
- medium – midrange but can be up to 10%.
- low – very low around 1 %
- off – no overhead
10%?!这是真的吗?我们不妨自己来测试一下!:
SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production PL/SQL Release 11.2.0.2.0 - Production CORE 11.2.0.2.0 Production TNS for Linux: Version 11.2.0.2.0 - Production NLSRTL Version 11.2.0.2.0 - Production SQL> create table MACLEAN(t1 int,t2 char(20),t3 char(20),t4 char(20), t5 char(20),t6 date) tablespace users; Table created. SQL> create or replace procedure insert_data(s int) as 2 begin 3 for i in 1..s loop 4 insert into MACLEAN values(i,'A','B','C','D',sysdate); 5 commit; 6 end loop; 7 end; 8 / Procedure created. SQL> show parameter db_block_checking NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_block_checking string FALSE SQL> begin 2 /* NON_CHECKING_50000 */ 3 insert_data(50000); 4 end; 5 / truncate table MACLEAN; alter system flush buffer_cache; begin /* NON_CHECKING_100000 */ insert_data(100000); end; / truncate table MACLEAN; alter system flush buffer_cache; begin /* NON_CHECKING_150000 */ insert_data(150000); end; / truncate table MACLEAN; alter system flush buffer_cache; alter system set db_block_checking=TRUE; begin /* DO_CHECKING_50000 */ insert_data(50000); end; / truncate table MACLEAN; alter system flush buffer_cache; begin /* DO_CHECKING_100000 */ insert_data(100000); end; / truncate table MACLEAN; alter system flush buffer_cache; begin /* DO_CHECKING_150000 */ insert_data(150000); end; / PL/SQL procedure successfully completed. SQL> SQL> SQL> Table truncated. SQL> System altered. SQL> SQL> 2 3 4 5 PL/SQL procedure successfully completed. SQL> SQL> Table truncated. SQL> System altered. SQL> SQL> 2 3 4 5 PL/SQL procedure successfully completed. SQL> SQL> Table truncated. SQL> System altered. SQL> SQL> System altered. SQL> SQL> 2 3 4 5 PL/SQL procedure successfully completed. SQL> SQL> SQL> Table truncated. SQL> System altered. SQL> SQL> 2 3 4 5 PL/SQL procedure successfully completed. SQL> SQL> Table truncated. SQL> System altered. SQL> SQL> 2 3 4 5 PL/SQL procedure successfully completed. SQL> SQL> SQL> SQL> SQL> SQL> SQL> col sql_text for a70; SQL> select sql_text, cpu_time, elapsed_time 2 from v$sql 3 where sql_text like '%CHECKING%' 4 and sql_text not like '%v$sql%' 5 order by CPU_TIME; SQL_TEXT CPU_TIME ELAPSED_TIME ---------------------------------------------------------------------- ---------- ------------ begin /* NON_CHECKING_50000 */ insert_data(50000); end; 7222902 7675162 begin /* DO_CHECKING_50000 */ insert_data(50000); end; 8285740 8522438 begin /* NON_CHECKING_100000 */ insert_data(100000); end; 13142002 13327092 begin /* DO_CHECKING_100000 */ insert_data(100000); end; 15353665 15686535 begin /* NON_CHECKING_150000 */ insert_data(150000); end; 19346058 19502160 begin /* DO_CHECKING_150000 */ insert_data(150000); end; 25374143 26539033 6 rows selected.
可以看到在面对频繁的dml操作时(模拟OLTP环境),DB_BLOCK_CHECKING为TRUE对CPU资源的使用影响可能远大于10%;实际上只有极少数对数据完整性要求异常苛刻的环境中,我们才会使用到它。
Comment