Remember the function compilation hang caused by library cache lock/library cache pin, analysis and processing process

I. Introduction

When the business is performing alter function my_function_name compile, it will normally be very fast (when it does not involve the inaccessible dblink), but early this morning, the business told me that they have two functions that cannot be compiled. The phenomenon is It will hang, and I need to analyze and deal with the problem.

2. Troubleshooting

When I saw this problem, I thought at first that the database must be locked, which caused the execution of the statement in the compilation process to fail. Therefore, the first time to check whether there are row locks in the database:

SQL> @block

no rows selected

It can be seen that there is no row lock in the database at this time.

At this point, I manually execute the compilation process of this function in sqlplus:

SQL> select * from v$mystat where rownum<2;

       SID STATISTIC#      VALUE
---------- ---------- ----------
      4994          0          0

SQL>alter function XXX compile;

Indeed, it was found that the compilation process was working.

Next, open another session to view the running status, waiting events and blocking status of the session:

SQL> select sid,seq#,event,wait_class from v$session_wait where sid=4994;

                                           WAIT
       SID       SEQ# EVENT                CLASS
---------- ---------- -------------------- ---------------
      4994         41 library cache lock   Concurrency

It can be found that the session that executes function compilation is blocked by the session whose sid is 368, and the waiting event of this session is library cache lock, and the wait_class is Concurrency.

So, under what circumstances may the library cache lock wait for events and block the session?

From the official documentation, we can see that the library cache lock waiting event is described as follows:

This event controls the concurrency between clients of the library cache. It acquires a lock on the object handle so that either:

  • One client can prevent other clients from accessing the same object.

  • The client can maintain a dependency for a long time (for example, so that no other client can change the object).

This lock is also obtained to locate an object in the library cache.

Library cache lock will be obtained on database objects referenced during parsing or compiling of SQL or PL/SQL statements (table, view, procedure, function, package, package body, trigger, index, cluster, synonym). The lock will be released at the end of the parse or compilation.

Cursors (SQL and PL/SQL areas), pipes and any other transient objects do not use this lock.

Library cache lock is not deadlock sensitive and the operation is synchronous.

From the above description, it can be understood that the library cache lock/pin is when two clients simultaneously access (modify) the same database object (usually table, view, procedure, function, package, package body, trigger, index , cluster, synonym, etc.), the session that first accesses the object will get a library lock on the object, thereby preventing other sessions from accessing the object or modifying or defining the object. The latter access (modification) session will wait for the events 'library cache pin' and 'library cache lock'.

In addition, one thing we need to know is:
library cache pin/lock will have three modes:

  • NULL
  • SHARE
  • EXCLUSIVE

When reading a database object, the session will obtain a lock/pin in SHARE mode;
when modifying a database object, the session will obtain a lock/pin in Exclusive mode;

The lock/pin of the share will block the lock/pin of the exclusive, thus generating waiting events related to the library cache pin/lock.

For different operations, the locks obtained are as follows:
All DDL operations (including compilation of procedures, functions, views, etc.) will request exclusive mode lock and pin for the access object;

Through the above description, we can probably see some reasons why the compilation fails, that is, there are other sessions accessing this function object.
Therefore, we can further check whether this session is blocked by other sessions: There are
many ways to check here:
Method 1: Check whether there are other sessions accessing this function:

select sid,owner,object,type from v$access where object='&function_name';

However, the query speed of this method is relatively slow, so it is not recommended to use;

Method 2: Use v$session to check whether the session is blocked by other sessions:

SQL> select sid,seq#,blocking_session,wait_class from v$session where sid=4994;

                                           WAIT
       SID       SEQ# BLOCKING_SESSIO EVENT                CLASS
---------- ---------- --------------- -------------------- ---------------
      4994         41             368 library cache lock   Concurrency

Method 3: via script

SQL>@we.sql

.....
   library cache lock sqlplus@resdb02 (TNS V  SYS|514|41             4994:16947:50814          A.W..51KS  ALT C.732shxcb178fv:0  F.2.368         515   oracle@[email protected]    -1:0:0:0
.....

At this point, we can see through the above methods that when we execute the alert function XXXX compile, the session is blocked by the session with SID 368.

So what is the 368 session doing? Are you accessing this function?
We can also find the sql_id of this session through v$session, and view the sql_text of the sql_id:

select sql_id from v$session where sid=368;
=========================================================
71bwdwbbwsrx5

select sql_text from v$sql where sql_id='71bwdwbbwsrx5';
=========================================================
begin  
-- Call the procedure   
p_test_XXXXk(v_anid =>:v_anid);
end;

It can be seen that this SQL mainly calls the p_test_fn_check_datatrunk process, and checks the DDL of the process through getddl:

SELECT DBMS_METADATA.GET_DDL('PROCEDURE','P_TEST_FN_CHECK_XXXX','CHENGDU') FROM DUAL;
================================================================================================
  CREATE OR REPLACE PROCEDURE "RES_CL"."P_TEST_XXXX" (v_anid in varchar2) as
       v_result varchar2(100);
begin

   v_result := chengdu.XXXXX(v_anid);
end;

At this point, you can see that the process uses this function.

3. Root cause of the problem

Therefore, the whole chain is very clear, that is,
1) session 368 calls the P_TEST_FN_CHECK_XXXX process, and the P_TEST_FN_CHECK_XXXX process will access the XXXX function; at this time, the database acquires the lock of the shared library cache on the XXXX function.
2) When the new session 4994 compiles the function XXXX, it will try to obtain the EXCLUSIVE lock.
3) The share lock will block the exclusive lock. Therefore, the compile operation of session 4994 is blocked and cannot be executed normally. After 5 minutes, an ORA-4021 error will be generated, and the timeout will be interrupted.

4. Problem solving

After the exception chain is clear, the problem handling becomes very simple. I inquired about the status of the 368 session, found that it was still active, and informed the user. If the user agrees, kill the session. Tried to compile again, and found that the compilation was completed normally.

V. Summary

Through this exception handling, we can have an in-depth understanding of the principles of library cache pin and library cache lock waiting events, know when and what lock or pin the library cache will obtain, and help us analyze and deal with problems.

Guess you like

Origin blog.csdn.net/wx370092877/article/details/109596329