Skip to Main Content
  • Questions
  • SQL fetch phase need library cache lock/pin

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question.

Asked: March 05, 2019 - 4:19 am UTC

Last updated: March 18, 2019 - 10:03 am UTC

Version: 11

Viewed 1000+ times

You Asked

Hi , thks for all your works here,i've learnd much a lot!
now, i have some question on SQL fetch phase and library cache lock/pin which stuck me for days.

here is something i find from some website,
SELECT statement follows following steps
1. parse : acquires library cache lock(aka DDL lock) and downgrade it to
null mode(aka breakable parse lock)
2. execute : acquires library cache pin and release it
3. fetch: breakable parse lock
4. close: release breakable parse lock


also from another site, https://www.oreilly.com/library/view/oracle-internals-an/156592598X/ch04s05.html
Library cache locks can only be broken, however, when the library cache object is not also pinned. A pin is applied to the library cache object for a PL/SQL program unit or SQL statement while it is being compiled, parsed, or executed. (no fetch)

from aboves,what i got is fetch phase does't REALLY NEED a library cache pin, from your site i also got that lets say A simple select query 'select * from a big_table' (1million-rows in big_table),does not read all rows at once, every fetch call return a slice rows ,use it,then next fetch call,next slice. etc..

my question is :
1> when an fetch call executing,isn't really need a library cache pin,to pin the execution plan in the shared pool?cascade to pin(share) the big_table too? if not,how can it be sure when executing but prevent any DDL on the big_table? will be a mess?
2> what if after the first fetch call then i drop the table big_table, will the second fetch call can aware that(invalidation occurred? )? continue fetch/return rows or return some errors?

long to short,
* from the parse,execution steps ,i can realize how library cache lock/pin works.
* but,in the FETCH step, will this step need library cache lock/pin or not? did every fetch call need get library cache lock(null) and library cache pin(share) and library cache lock/pin(depended objects) , if so, will that operation(fetch call) bring too much load(costs) to the database?

and Connor said...

We don't *guarantee* that a fetch will work for the duration of the query, because you might do a fetch, walk away for a week, and then come back. We can't really hold the table "locked" for an unknown duration. That's why we can allow things to happen to the table while you are fetching. You *might* get lucky...you might not. Here's a couple of examples:

--
-- Session 1
--

-- tine tablespace with room for just one table

SQL> create tablespace ROOM_FOR_ONE datafile 'X:\ORADATA\DB18\PDB1\ROOM_FOR_ONE.DBF' size 2m;

Tablespace created.

SQL> create table t tablespace room_for_one
  2  as select * from dba_objects
  3  where rownum <= 1000;

Table created.

SQL>
SQL>
SQL> set arraysize 50
SQL> set pagesize 55

--
-- pausing so we will fetch approx 50 rows at a time
--
SQL> set pause on
SQL> select owner, object_name from t;


OWNER                          OBJECT_NAME
------------------------------ -------------------------------------
SYS                            I_FILE#_BLOCK#
SYS                            I_OBJ3
SYS                            I_TS1
SYS                            I_CON1
SYS                            IND$
SYS                            CDEF$
SYS                            C_TS#
SYS                            I_CCOL2
SYS                            I_PROXY_DATA$
SYS                            I_CDEF4
SYS                            I_TAB1
SYS                            CLU$
SYS                            I_PROXY_ROLE_DATA$_1
SYS                            I_OBJ1
SYS                            UNDO$
SYS                            I_UNDO2
SYS                            I_TS#
SYS                            I_FILE1
SYS                            I_COL2
SYS                            I_OBJ#
SYS                            C_OBJ#
SYS                            I_CDEF3
SYS                            C_COBJ#

--
-- Session 2
--
SQL> drop table t purge;

Table dropped.

--
-- Session 1
--

SYS                            I_CON2
SYS                            I_OBJ4
SYS                            CON$
SYS                            I_CDEF2
SYS                            ICOL$
SYS                            I_COL3
SYS                            I_CCOL1
SYS                            COL$
SYS                            I_ICOL1
...
SYS                            STREAMS$_DEST_OBJS_I
SYS                            STREAMS$_DEST_OBJ_COLS
SYS                            STREAMS$_DEST_OBJ_COLS_I
SYS                            STREAMS$_PRIVILEGED_USER

1000 rows selected.


So you can that even though we *dropped* the table, we could still complete our query because the table data was still there. But let's repeat that now, and you'll see why I used a tiny tablespace:

SQL> create table t tablespace room_for_one
  2  as select * from dba_objects
  3  where rownum <= 1000;

Table created.

SQL>
SQL>
SQL> set arraysize 50
SQL> set pagesize 55

--
-- pausing so we will fetch approx 50 rows at a time
--
SQL> set pause on
SQL> select owner, object_name from t;


OWNER                          OBJECT_NAME
------------------------------ -------------------------------------
SYS                            I_FILE#_BLOCK#
SYS                            I_OBJ3
SYS                            I_TS1
SYS                            I_CON1
SYS                            IND$
SYS                            CDEF$
SYS                            C_TS#
SYS                            I_CCOL2
SYS                            I_PROXY_DATA$
SYS                            I_CDEF4
SYS                            I_TAB1
SYS                            CLU$
SYS                            I_PROXY_ROLE_DATA$_1
SYS                            I_OBJ1
SYS                            UNDO$
SYS                            I_UNDO2
SYS                            I_TS#
SYS                            I_FILE1
SYS                            I_COL2
SYS                            I_OBJ#
SYS                            C_OBJ#
SYS                            I_CDEF3
SYS                            C_COBJ#

--
-- Session 2
--
SQL> drop table t purge;

Table dropped.

SQL> create table t1 tablespace room_for_one
  2  as select * from dba_objects
  3  where rownum <= 1000;

Table created.

SQL>
SQL> insert into t1 select * from t1;

1000 rows created.

SQL> commit;

Commit complete.

SQL> insert into t1 select * from t1;

2000 rows created.

SQL> commit;

Commit complete.

SQL> insert into t1 select * from t1;
insert into t1 select * from t1
*
ERROR at line 1:
ORA-01653: unable to extend table T1 by 128 in tablespace ROOM_FOR_ONE

--
-- Session 1
--
(hit Enter to get the next set of rows)
ERROR:
ORA-08103: object no longer exists

150 rows selected.



When I created T1, because the tablespace was so small, I reused the space that T originally had occupied. The next fetch gets "garbage" back from the disk, and we know that our T no longer exists.

There's other examples where this can happen, eg





Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

many thanks

runa, March 11, 2019 - 5:53 am UTC

grate examples as always ! tons of thanks.;)

Again, a little more confuseing~

runa, March 12, 2019 - 9:49 am UTC

thanks, connor!
"We don't *guarantee* that a fetch will work for the duration of the query"
I got that!

but as explore similar with this topic, I found some conflict thing :

1. tom says:" the sql area representation of what plsql points to is subject to flushing just as any open cursor is. "
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2658940700346347478
--i thought this meaning when an cursor is in opening state (not close) *sql area representation* in share pool will be flush out when there is a space pressure on the share pool ? right?
2. but , link this https://asktom.oracle.com/pls/apex/asktom.search?tag=session-cursor-caching you said, "We're keeping more cursors open...which means they wont be flushed out of the shared pool...which if the shared pool was *really stressed* might be an issue."

Q:when an cursor is opening, meaning:


parse
execute
fetch
fetch
...
-- but not close


will the *sql area representation* in share pool flush out or not when the cursor is in open state?
I think it should not, because let's say,for example between fetchs , a invalidate occurs(a table being dropped), if the sql plan is flush out, next time fetch call run, may cause a reload ,but the table doesn't exists! reload is impossible it got failed, that's wrong, am i right ?
Connor McDonald
March 18, 2019 - 10:03 am UTC

That's a big topic.

Some things in the shared pool are flushable even if they are in use. They are deemed "recreatable", that is, the database has sufficient information to bring that information back into the shared pool if required.

To use your example: "if the sql plan is flush out, next time fetch call run", in most instances if that happens, the table will still exist so we reload memory with plan details, and continue on our way.

If the table *had* been dropped, then yes, we'd give an error when try to reload those details - and thats fine too, because the table is gone!

ideas!

runa, March 29, 2019 - 6:33 am UTC

aha!
I think i got the points!
THE consistency and Availability/Usability is the highest/supreme priority thing ORACLE really cares ,NOT a sql can run smoothly success or return an error.
oracle really guarantee return results must be accurate.
they can't lets some ordinary query sql(not DDL) stuck the database system stuttering again and again .

Long to short: db system's Availability/Concurrence is more more important than one query can run successful every time or not .

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database