V$SQL SHARED CURSOR

EXEM Knowledge Base

Jump to: navigation, 찾기

목차

[편집] 기본 정보

[편집] 개요

Child Cursor별로 Cursor 공유가 이루어지지 않은 이유를 제공하는 뷰이다. 가령 Bind Mismatch가 생긴 경우에는 BIND_MISMATCH 컬럼의 값이 Y로 기록된다.

[편집] 지원

8i 이상

[편집] 컬럼

이름 유형 설명
ADDRESS RAW(4) Address of the child cursor
KGLHDPAR RAW(4) Address of the parent cursor
UNBOUND_CURSOR VARCHAR2(1) N) The existing child cursor was not fully built (in other words, it was not optimized)
SQL_TYPE_MISMATCH VARCHAR2(1) N) The SQL type does not match the existing child cursor
OPTIMIZER_MISMATCH VARCHAR2(1) N) The optimizer environment does not match the existing child cursor
OUTLINE_MISMATCH VARCHAR2(1) N) The outlines do not match the existing child cursor
STATS_ROW_MISMATCH VARCHAR2(1) N) The existing statistics do not match the existing child cursor
LITERAL_MISMATCH VARCHAR2(1) N) Non-data literal values do not match the existing child cursor
SEC_DEPTH_MISMATCH VARCHAR2(1) N) Security level does not match the existing child cursor
EXPLAIN_PLAN_CURSOR VARCHAR2(1) N) The child cursor is an explain plan cursor and should not be shared
BUFFERED_DML_MISMATCH VARCHAR2(1) N) Buffered DML does not match the existing child cursor
PDML_ENV_MISMATCH VARCHAR2(1) N) PDML environment does not match the existing child cursor
INST_DRTLD_MISMATCH VARCHAR2(1) N) Insert direct load does not match the existing child cursor
SLAVE_QC_MISMATCH VARCHAR2(1) N) The existing child cursor is a slave cursor and the new one was issued by the coordinator (or, the existing child cursor was issued by the coordinator and the new one is a slave cursor)
TYPECHECK_MISMATCH VARCHAR2(1) N) The existing child cursor is not fully optimized
AUTH_CHECK_MISMATCH VARCHAR2(1) N) Authorization/translation check failed for the existing child cursor
BIND_MISMATCH VARCHAR2(1) N) The bind metadata does not match the existing child cursor
DESCRIBE_MISMATCH VARCHAR2(1) N) The typecheck heap is not present during the describe for the child cursor
LANGUAGE_MISMATCH VARCHAR2(1) N) The language handle does not match the existing child cursor
TRANSLATION_MISMATCH VARCHAR2(1) N) The base objects of the existing child cursor do not match
ROW_LEVEL_SEC_MISMATCH VARCHAR2(1) N) The row level security policies do not match
INSUFF_PRIVS VARCHAR2(1) N) Insufficient privileges on objects referenced by the existing child cursor
INSUFF_PRIVS_REM VARCHAR2(1) N) Insufficient privileges on remote objects referenced by the existing child cursor
REMOTE_TRANS_MISMATCH VARCHAR2(1) N) The remote base objects of the existing child cursor do not match
LOGMINER_SESSION_MISMATCH VARCHAR2(1) N)
INCOMP_LTRL_MISMATCH VARCHAR2(1) N)

[편집] 참고 사항

[편집] High Version Count

SQL Text는 동일하지만 공유되지 못하는 Child Cursor의 개수는 V$SQL_AREA.VERSION_COUNT 컬럼의 값으로 알 수 있다. 이 컬럼 값이 높은 경우를 흔히 Version Count가 높다고 표현한다. 높은 Version Count는 다음과 같은 문제와 관련이 있다.

Version Count가 지나치게 높은 경우에는 V$SQL_SHARED_CURSOR 뷰를 이용해서 Cursor가 공유되지 못하는 이유를 파악한 후 문제를 해결해야 한다.

[편집] Cursor가 공유되지 못하는 일반적인 이유들

  1. Optimizer Mode의 변경(ALL_ROWS/FIRST_ROWS/CHOOSE). OPTIMIZER_MODE_MISMATCH 컬럼값으로 확인
  2. Optimizer Parameter의 변경(예: OPTIMIZER_INDEX_CACHING 파라미터). OPTIMIZER_MISMATCH 컬럼값으로 확인
  3. Trace Event 활성화(예: 10046 Event, DBMS_MONITOR, SQL_TRACE). STATS_ROW_MISMATCH 컬럼값으로 확인
  4. Translation 발생(예: Schema A와 Schema B가 동일한 이름의 테이블을 사용). AUTH_CHECK_MISMATCH, TRANSLATION_MISMATCH 컬럼값으로 확인
  5. Bind Mismatch 발생(예: 길이가 다른 문자열 사용). BIND_MISMATCH 컬럼값으로 확인


[편집] 예제

[편집] Bind Mismatch에 의한 Version Count 증가

동일한 Bind 변수에 대해 서로 길이가 다른 값을 사용하면 Bind Mismatch가 발생할 수 있다. 아래의 예를 보자.

-- 동일한 Text의 SQL을 Bind 변수의 길이를 변경하며 수행
var x varchar2(1);
exec :x := 't';
select /* bind_test */ * from bind_test where name = :x;

var x varchar2(150);
exec :x := 't';
select /* bind_test */ * from bind_test where name = :x;

var x varchar2(300);
exec :x := 't';
select /* bind_test */ * from bind_test where name = :x;
-- Version Count가 3으로 모두 공유되지 못했음을 확인할 수 있다.
SELECT version_count, sql_text FROM v$sqlarea WHERE sql_text like 'select /* bind_test */%';
version_count   sql_text   
----------------   --------------------------------------------------------------------                                                             
3                    select /* bind_test */ * from bind_test where name = :x

오라클은 Varchar 타입의 Bind 변수의 경우 그 길이를 다음과 같은 구간의 값으로 올림한다.

  • 32
  • 128
  • 2000
  • 4000

같은 구간 사이에 속하는 길이는 Bind 변수는 동일한 길이로 취급되지만, 구간이 다른 경우에는 Bind Mismatch가 발생한다. V$SQL_BIND_METADATA 뷰를 이용하면 이것을 확인할 수 있다.

select address, max_length, bind_name from v$sql_bind_metadata
     where child_address in (
        SELECT child_address FROM v$sql WHERE sql_text like 'SELECT /* bind_test */%'
     );
address                         max_length            bind_name
-----------------------         ---------------           -------------
0000000084884B10               32                       X
0000000084973280               128                      X
0000000084973E70               2000                    X

위와 같은 현상을 없애려면 동일한 크기의 Bind 변수를 선언해야 한다.

Java 언어에서는 PreparedStatement를 통해 Bind 변수를 사용한다. 이 경우에도 동일한 문제가 발생한다. 즉, 아래의 두 PreparedStatement는 실제로는 공유가 되지 못한다.

PreparedStatement stmt = null;
String s1 = "a";
stmt = con.prepareStatement("SELECT /* bind_test */ * FROM bind_test WHERE name = ?");
stmt.setString(1, s1);
ResultSet rs = stmt.executeQuery();
stmt.close();

String s2 = "a";
for(int idx=0; idx<50; idx++) s2 = s2+" ";
stmt = con.prepareStatement("SELECT /* bind_test */ * FROM bind_test WHERE name = ?");
stmt.setString(1, s2);
rs = stmt.executeQuery();
stmt.close();

이러한 현상은 대부분의 경우 큰 문제가 되지 않는다. 하지만 하나의 SQL 문장이 많은 수의 Bind 변수를 사용하고, 각 Bind 변수마다 Bind Mismatch개 발생할 경우 그 경우의 수는 기하급수적으로 늘어날 수 있다. 이런 경우에는 다음과 같은 방법을 사용할 수 있다.

String x = "x";
// V$SQL_BIND_METADATA 뷰를 통해 확인한 최대값만큼 Dummy Blank를 붙인다.
for(int i=0; i<xxxx; i++) x+= " ";
...
// RTRIM Function을 사용해서 Dummy Blank가 인식되지 않도록 한다.
stmt = con.prepareStatement("select /* bind_test */ * from bind_test where name = RTRIM(?)");
..

위와 같이 코드를 수정하면 항상 같은 크기의 문자열이 전송되므로, Bind Mismatch가 발생하지 않는다.


[편집] 관련 정보

  1. V$SQL_BIND_METADATA


[편집] 외부 참조

  1. Library Cache Internals - Julian Dyke