SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
--aiki下创建一实体表T1
SQL> create table t1 as select * from dba_objects where object_id is not null;
Table created.
SQL> create index idx_t1_id on t1(object_id);
Index created.
SQL> select status from t1 where object_id=33;
STATUS
-------
VALID
SQL> /
STATUS
-------
VALID
SQL> /
STATUS
-------
VALID
--生成SQL_ID,PHV(PLAN HASH VALUE)
SQL> @all
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 71v4d139gzpzq, child number 0
-------------------------------------
select status from t1 where object_id=33
Plan hash value: 190799060
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 18 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T1_ID | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
2 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=33)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
2 - "T1".ROWID[ROWID,10]
Note
-----
- dynamic sampling used for this statement (level=2)
--采用SPM绑定
SQL> declare
2 aa binary_integer;
3 begin
4 aa:=DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id=>'71v4d139gzpzq',PLAN_HASH_VALUE=>190799060,FIXED=>'YES',ENABLED=>'YES');
5 return ;
6 end;
7 /
PL/SQL procedure successfully completed.
--查看baseline视图,已经绑定计划
1* select SQL_TEXT,PLAN_NAME,ENABLED,ACCEPTED,FIXED from dba_sql_plan_baselines
SQL> /
SQL_TEXT PLAN_NAME ENA ACC FIX
-------------------------------------------------- ------------------------------ --- --- ---
select status from t1 where object_id=33 SQL_PLAN_b6tztbgtkhqdt74b15d2b YES YES YES
--在Note部份可以看到baseline绑定已经生效,是走索引的
--SQL plan baseline SQL_PLAN_b6tztbgtkhqdt74b15d2b used for this statement
SQL> @all
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 71v4d139gzpzq, child number 1
-------------------------------------
select status from t1 where object_id=33
Plan hash value: 190799060
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 18 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T1_ID | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
2 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=33)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
2 - "T1".ROWID[ROWID,10]
Note
-----
- dynamic sampling used for this statement (level=2)
- SQL plan baseline SQL_PLAN_b6tztbgtkhqdt74b15d2b used for this statement
--看下内存中此SQL的游标分布,子游标号为2,0为父游标,phv:190799060
SQL_ID CHILD_NUMBER PLAN_HASH_VALUE
------------- ------------ ---------------
71v4d139gzpzq 0 190799060
71v4d139gzpzq 2 190799060
--在用户AIKI2下创建一实体表T1,但无索引
--可以看到baseline对它不生效,因为
create table t1 as select * from dba_objects where object_Id is not null;
SQL> select status from t1 where object_id=33;
STATUS
-------
VALID
SQL> select status from t1 where object_id=33;
STATUS
-------
VALID
SQL> select status from t1 where object_id=33;
STATUS
-------
VALID
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 71v4d139gzpzq, child number 1
-------------------------------------
select status from t1 where object_id=33
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 300 (100)| |
|* 1 | TABLE ACCESS FULL| T1 | 12 | 216 | 300 (1)| 00:00:04 |
--------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=33)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
Note
-----
- dynamic sampling used for this statement (level=2)
--再次检查下可以发现子游标为2的游标已经被刷出内存,而取代它的是子游标为1的游标,phv:3617692013
select sql_id,child_number,plan_hash_value from v$sql where sql_id='71v4d139gzpzq'
SQL_ID CHILD_NUMBER PLAN_HASH_VALUE
------------- ------------ ---------------
71v4d139gzpzq 0 190799060
71v4d139gzpzq 1 3617692013
--小结下:可以发现两条SQL_ID一样SQL,执行计划不同而导致两个执行计划的游标相互竞争,有你没我;
--严重后果:在我国很多企业都是按省市下的地市来做业务,同一个库中包含多个地市的模型,而且大多
--模型结果相同;当某SQL由于性能原因而采用SPM进行稳固,且fixes=>yes时得万分小心,否则将引由于
--其中1SQL游标被刷出而再次高并发登录时产生大规模的library cache lock事件,导致CPU资源被耗光;
--这个已经碰到过一次了;
=》我们来看第2种情况,当两者之间也是SQL_ID相同而模型结构不同导致的执行计划不同时的情况;
AIKI2用户建为视图:
SQL> create view t2 as select distinct object_id,status,owner from dba_objects where object_id is not null;
View created.
AIKI用户建为实体表:
SQL> create table t2 as select object_id,status,owner from dba_objects where object_id is not null;
Table created.
--AIKI用户下运行,sql_id:d7y1m4pt52xwd,phv:1513984157
select status from t2 where object_id=55;
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID d7y1m4pt52xwd, child number 0
-------------------------------------
select status from t2 where object_id=55
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 67 (100)| |
|* 1 | TABLE ACCESS FULL| T2 | 3 | 54 | 67 (2)| 00:00:01 |
--------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T2@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=55)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
Note
-----
- dynamic sampling used for this statement (level=2)
32 rows selected.
--进行计划的稳固绑定
SQL> declare
2 aa binary_integer;
3 begin
4 aa:=DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id=>'d7y1m4pt52xwd',PLAN_HASH_VALUE=>1513984157,FIXED=>'YES',ENABLED=>'YES');
5 return ;
6 end;
7 /
PL/SQL procedure successfully completed.
--查看已经生效
SQL> select SQL_TEXT,PLAN_NAME,ENABLED,ACCEPTED,FIXED from dba_sql_plan_baselines
2 /
SQL_TEXT PLAN_NAME ENA ACC FIX
-------------------------------------------------- ------------------------------ --- --- ---
select status from t2 where object_id=55 SQL_PLAN_7j9ssum4sn3fkb860bcf2 YES YES YES
SQL> @all
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID d7y1m4pt52xwd, child number 1
-------------------------------------
select status from t2 where object_id=55
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 67 (100)| |
|* 1 | TABLE ACCESS FULL| T2 | 3 | 54 | 67 (2)| 00:00:01 |
--------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T2@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=55)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "STATUS"[VARCHAR2,7]
Note
-----
- dynamic sampling used for this statement (level=2)
- SQL plan baseline SQL_PLAN_7j9ssum4sn3fkb860bcf2 used for this statement
33 rows selected.
--检查下当前的游标情况:SQL_ID:d7y1m4pt52xwd,子游标:1,PHV:1513984157
SQL> select sql_id,child_number,plan_hash_value from v$sql where sql_id='d7y1m4pt52xwd';
SQL_ID CHILD_NUMBER PLAN_HASH_VALUE
------------- ------------ ---------------
d7y1m4pt52xwd 0 1513984157
d7y1m4pt52xwd 1 1513984157
--在AIKI2用户上运行
SQL> select status from t2 where object_id=55;
STATUS
-------
VALID
SQL> /
STATUS
-------
VALID
SQL> /
STATUS
-------
VALID
SQL> /
STATUS
-------
VALID
SQL> /
SQL_ID CHILD_NUMBER PLAN_HASH_VALUE
------------- ------------ ---------------
d7y1m4pt52xwd 0 1513984157
d7y1m4pt52xwd 2 3629752164
aiki下再次执行,可以看到情况和第一次实验完全相同;
SQL> select status from t2 where object_id=55;
STATUS
-------
VALID
SQL> /
STATUS
-------
VALID
SQL> /
SQL_ID CHILD_NUMBER PLAN_HASH_VALUE
------------- ------------ ---------------
d7y1m4pt52xwd 0 1513984157
d7y1m4pt52xwd 1 1513984157
--可以看到情况与上面一样;
这里纠正个问题,昨天写得不全面重改了以下部份;
以于FIXED=YES的情况,才会导到多个会话间相互挤兑而引起的高并发下的大量library cache lock事件;
由于实验过于繁琐冗长,我这里只写下小结,详细的证明可以自行去实验下;
假定会话1叫S1,会话2叫S2,以及它们的计划和通用性;如下所示:
会话 SQL_ID phv FIXED S1兼容S2 S1不兼容S2
S1 sqlid1 phv1 YES 不相互挤兑 相互挤兑
S2 sqlid1 phv2 NO 不相互挤兑 相互挤兑
补充备注:
当S1的FIXED=NO,S2不兼容时会自动将它的执行计划添加到BSLINE,默认accepted=no,但不发生挤兑;
当S1的FIXED=NO,S2兼容时会自动将它的最优执行计划添加到BSLINE,默认accepted=no,但不发生挤兑,同时使用S1的执行计划而不是它的最优计划;
当S1,S2都在BSLINE时FIXED=YES OR NO时两者是平等的;
这个实验最好自己去试下才会清楚,容易搞混;