Re: a strange behavior in Oracle 12.2.0.1 by nested PLSQL cursor
Date: Tue, 29 Jan 2019 16:28:40 +0000
Message-ID: <CACj1VR6+XAvZZO851qM=BQL29qZ2-pkoci=y1haLYabycKQp2Q_at_mail.gmail.com>
Okay,
I ran your test and got no output on 12.2.01
Traced it (10046 level 4)
Found that the query against all_constraints went parallel and returned no
data, so added a /*+ noparallel */ hint to the query, then (belts and
braces) "alter session disable parallel query;"
Ran the test again - got the expected result.
It looks like the parallel execution loses the value of sys_context.
I would check whether 12.1.0.2 and 11.2.0.4 ran the query parallel or
whether they ran it serially, and if they're running t serially check what
happens if you force it parallel.
- After the no_merge comment:
That (ed. the no_merge) may be luck rather than anything else. I just tried the same thing and still saw the problem (and parallel execution). In your case it's possible that the presence of the no_merge hint resulted in Oracle materializing the subquery and maybe that made it run serially - i.e. it was about object_statistics rather than functionality.
P.S. Looking at the execution plans, my 12.2 (corrected from 12.1) is translating all_constraints to a query involving int$int$DBA_CONSTRAINTS, while the 12.1 query is a "more traditional" massive join of lots of tables - so the base problem seems to start with the appearance of a CDB-mechanism of all_constraints. (I'm running 12.2. from a PDB, while the 12.1 is non-PDB database)
On Tue, 29 Jan 2019 at 16:19, Ahmed <gherrami_at_gmail.com> wrote:
> Hi Andy,
>
> I tested two variants of the block. Once with ref cursor and bind variable
> and once without explicit cursor. So dynamic code using bind variable and
> insert bulk collect.
> The result is always the same (works everywhere but not on my 12.2).
> With the no_merge hint works everywhere.
>
> The no_merge workaround is sure not a reasonable solution. I have
> completely rewritten the block. I'm not a fan of such nested loops anyway.
>
>
> See the two PL / SQL block bellow.
>
> Thanks and Regards
>
> --using ref cursor
> DECLARE
> -- table that has Foreignkey pointing on it
> v_tbl_name VARCHAR2(30) := 'PARENT';
> v_tbl_child VARCHAR2(30);
> v_cons_name VARCHAR2(30);
> CURSOR get_massdata_tableinfo
> IS
> SELECT v_tbl_name table_name FROM dual
>
> ;
> get_fks_as_refcursr sys_refcursor;
> v_stmt VARCHAR2(4000) := 'WITH
> user_constr AS
> (
> SELECT *
> FROM all_constraints
> WHERE owner = sys_context(''USERENV'', ''CURRENT_SCHEMA'')
> )
> SELECT r.constraint_name,
> r.table_name
> FROM user_constr r,
> user_constr t
> WHERE t.table_name = :par_target_table
> AND t.constraint_type = ''P''
> AND t.constraint_name = r.r_constraint_name';
>
> BEGIN
> FOR crec IN get_massdata_tableinfo
> LOOP
> --
> dbms_output.put_line('Table Name ' || crec.table_name);
> -- disable FK´s pointing to table
> OPEN get_fks_as_refcursr FOR v_stmt USING crec.table_name ;
>
> LOOP
> FETCH get_fks_as_refcursr INTO v_cons_name,v_tbl_child;
> EXIT WHEN get_fks_as_refcursr%NOTFOUND;
> dbms_output.put_line('ALTER TABLE ' || v_tbl_child||
> ' DISABLE CONSTRAINT ' || v_cons_name);
>
> END LOOP;
> CLOSE get_fks_as_refcursr ;
> END LOOP;
> END;
>
> --using dynamic sql + bind variable
> DECLARE
> -- table that has Foreignkey pointing on it
> v_tbl_name VARCHAR2(30) := 'PARENT';
> v_tbl_child sys.odcivarchar2list := sys.odcivarchar2list();
> v_cons_name sys.odcivarchar2list := sys.odcivarchar2list();
>
> CURSOR get_massdata_tableinfo
> IS
> SELECT v_tbl_name table_name FROM dual
>
> ;
> v_stmt VARCHAR2(4000) := 'WITH
> user_constr AS
> (
> SELECT *
> FROM all_constraints
> WHERE owner = sys_context(''USERENV'', ''CURRENT_SCHEMA'')
> )
> SELECT r.constraint_name,
> r.table_name
> FROM user_constr r,
> user_constr t
> WHERE t.table_name = :par_target_table
> AND t.constraint_type = ''P''
> AND t.constraint_name = r.r_constraint_name';
>
> BEGIN
> FOR crec IN get_massdata_tableinfo
> LOOP
> --
> dbms_output.put_line('Table Name ' || crec.table_name);
> -- disable FK´s pointing to table
> EXECUTE IMMEDIATE v_stmt BULK COLLECT INTO v_cons_name,v_tbl_child
> USING crec.table_name;
> FOR i IN 1..v_cons_name.count LOOP
> dbms_output.put_line('ALTER TABLE ' || v_tbl_child(i)||
> ' DISABLE CONSTRAINT ' || v_cons_name(i));
>
> END LOOP;
> END LOOP;
> END;
>
> Am Di., 29. Jan. 2019 um 15:12 Uhr schrieb Ahmed <gherrami_at_gmail.com>:
>
>> It's already a cursor. As you can also see in the example.
>> We believe that this is an Oracle bug. Also in 12.1 we had to deal with
>> similar things.
>>
>> Regards
>> Ahmed
>>
>> Am Di., 29. Jan. 2019 um 15:00 Uhr schrieb Andy Sayer <
>> andysayer_at_gmail.com>:
>>
>>> It works for me in the pl/sql on 12.2.0.1 with JAN2019 patch set.
>>>
>>> Your notes on the no_merge helping suggest that this is a bug caused by
>>> some rewrite.
>>>
>>> Difference in behaviour between pl/sql and sql might be due to the
>>> implicit bind variable being used in the pl/sql, try using binds in your
>>> sql to see if the problem occurs.
>>>
>>> Hope that helps,
>>> Andy
>>>
>>>
>>> On Tue, 29 Jan 2019 at 13:29, Ahmed <gherrami_at_gmail.com> wrote:
>>>
>>>> I first built the workaround with no_merge, so I can do at least a
>>>> regression test.
>>>> The regression took about an hour. (should take about 25 minutes .In
>>>> regression, we have only a few data. But at least no crashes or any
>>>> Ora-00600 errors.).
>>>> Looks like the upgrading will make us headache.
>>>>
>>>> If the regression is over, I'll start a performance test see which SQL
>>>> become slower.
>>>>
>>>> Your suggestion sounds interesting concerning the performance.
>>>>
>>>> Thanks
>>>>
>>>> Am Di., 29. Jan. 2019 um 14:04 Uhr schrieb kathy duret <
>>>> katpopins21_at_yahoo.com>:
>>>>
>>>>> Didn't read the thread and someone may have suggested this already but
>>>>> we have turned off the adaptive tuning feature in 12.1 .
>>>>>
>>>>> You might try turning it off in a lower environment and see how things
>>>>> perform afterwards.
>>>>>
>>>>> I think Oracle is "retooling" this feature in the future. We are
>>>>> skipping 12.2 and going to 12.3 due to some bugs.
>>>>>
>>>>> Good Luck
>>>>>
>>>>>
>>>>> Kathy Duret
>>>>>
>>>>>
>>>>>
>>>>> On Tuesday, January 29, 2019, 4:29:04 AM CST, Ahmed <
>>>>> gherrami_at_gmail.com> wrote:
>>>>>
>>>>>
>>>>> A colleague came up with the idea to use a no_merge hint. Then
>>>>> everything works again. Very strange.
>>>>>
>>>>> CURSOR get_fks(par_target_table user_tables.table_name%TYPE)
>>>>> IS
>>>>> WITH
>>>>> user_constr AS
>>>>> (
>>>>> SELECT /*+ no_merge */ *
>>>>> FROM all_constraints
>>>>> WHERE owner = sys_context('USERENV', 'CURRENT_SCHEMA')
>>>>> )
>>>>> SELECT r.constraint_name,
>>>>> r.table_name
>>>>> FROM user_constr r,
>>>>> user_constr t
>>>>> WHERE t.table_name = par_target_table
>>>>> AND t.constraint_type = 'P'
>>>>> AND t.constraint_name = r.r_constraint_name
>>>>> ;
>>>>>
>>>>> Regards
>>>>> Ahmed Fikri
>>>>>
>>>>> Am Di., 29. Jan. 2019 um 10:33 Uhr schrieb Ahmed <gherrami_at_gmail.com>:
>>>>>
>>>>> Yes the schema running the code is the same as the schema owning the
>>>>> tables
>>>>>
>>>>> That's what I did:
>>>>>
>>>>> CREATE USER tester IDENTIFIED BY tester QUOTA 10M ON USERS;
>>>>> GRANT CREATE SESSION TO tester;
>>>>> GRANT CREATE TABLE TO tester;
>>>>> -- after loggon as tester
>>>>> CREATE TABLE PARENT(ID NUMBER PRIMARY KEY);
>>>>> CREATE TABLE PARENT(ID NUMBER PRIMARY KEY);
>>>>> CREATE TABLE CHILD(ID NUMBER, parent_id NUMBER ,CONSTRAINT FOREIGN KEY
>>>>> REFERENCES PARENT(ID));
>>>>>
>>>>> DECLARE
>>>>> -- table that has Foreignkey pointing on it
>>>>> v_tbl_name VARCHAR2(30) := 'PARENT';
>>>>> CURSOR get_massdata_tableinfo
>>>>> IS
>>>>> SELECT v_tbl_name table_name FROM dual
>>>>>
>>>>> ;
>>>>> CURSOR get_fks(par_target_table user_tables.table_name%TYPE)
>>>>> IS
>>>>> WITH
>>>>> user_constr AS
>>>>> (
>>>>> SELECT *
>>>>> FROM all_constraints
>>>>> WHERE owner = sys_context('USERENV', 'CURRENT_SCHEMA')
>>>>> )
>>>>> SELECT r.constraint_name,
>>>>> r.table_name
>>>>> FROM user_constr r,
>>>>> user_constr t
>>>>> WHERE t.table_name = par_target_table
>>>>> AND t.constraint_type = 'P'
>>>>> AND t.constraint_name = r.r_constraint_name
>>>>> ;
>>>>> BEGIN
>>>>> FOR crec IN get_massdata_tableinfo
>>>>> LOOP
>>>>> --
>>>>> dbms_output.put_line('Table Name ' || crec.table_name);
>>>>> -- disable FK´s pointing to table
>>>>> FOR rec IN get_fks(crec.table_name) --no rows in 12.2.0.1 (but
>>>>> it works in 11.2.0.4 and 12.1.0.2)
>>>>> LOOP
>>>>> dbms_output.put_line('ALTER TABLE ' || rec.table_name ||
>>>>> ' DISABLE CONSTRAINT ' || rec.constraint_name);
>>>>>
>>>>> END LOOP;
>>>>> END LOOP;
>>>>>
>>>>> END;
>>>>>
>>>>> I get AS Output:
>>>>> Table Name PARENT
>>>>>
>>>>> But on 11.2.0.4 or 12.1.0.2-- the same steps I get as Output:
>>>>> Table Name PARENT
>>>>> ALTER TABLE CHILD DISABLE CONSTRAINT SYS_C00444321
>>>>>
>>>>> This confuses me
>>>>>
>>>>> The context of these error is an attempt to upgrade our software from
>>>>> 11.2.0.4 to 12.2.0.1.
>>>>> Everything works fine on 11.2.0.4. In the example block above I try to
>>>>> summarize only the error here in this list.
>>>>>
>>>>> we have patched the following patch.
>>>>>
>>>>> ARU platform id: 226
>>>>>
>>>>> ARU platform description:: Linux x86-64
>>>>>
>>>>>
>>>>>
>>>>> Installed Top-level Products (1):
>>>>>
>>>>>
>>>>>
>>>>> Oracle Database 12c
>>>>> 12.2.0.1.0
>>>>>
>>>>> There are 1 products installed in this Oracle Home.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Interim patches (1) :
>>>>>
>>>>>
>>>>>
>>>>> Patch 28662603 : applied on Sat Nov 24 14:07:07 CET 2018
>>>>>
>>>>> Unique Patch ID: 22485591
>>>>>
>>>>> Patch description: "Database Oct 2018 Release Update :
>>>>> 12.2.0.1.181016 (28662603)"
>>>>> Created on 5 Oct 2018, 03:26:32 hrs PST8PDT
>>>>>
>>>>> Regards
>>>>> Ahmed Fikri
>>>>>
>>>>> Am Di., 29. Jan. 2019 um 10:05 Uhr schrieb Jonathan Lewis <
>>>>> jonathan_at_jlcomp.demon.co.uk>:
>>>>>
>>>>>
>>>>> It works for me on an unpatched 12.2.0.1
>>>>>
>>>>> In my case I log in, create a parent and child table, then run your
>>>>> code. Is the schema running your code the same as the schema owning the
>>>>> tables ?
>>>>> Could there be a difference in privileges rather than a bug.
>>>>>
>>>>> Regards
>>>>> Jonathan Lewis
>>>>>
>>>>>
>>>>>
>>>>> ________________________________________
>>>>> From: oracle-l-bounce_at_freelists.org <oracle-l-bounce_at_freelists.org>
>>>>> on behalf of Ahmed <gherrami_at_gmail.com>
>>>>> Sent: 28 January 2019 14:57
>>>>> To: ORACLE-L
>>>>> Subject: a strange behavior in Oracle 12.2.0.1 by nested PLSQL cursor
>>>>>
>>>>> Hi,
>>>>>
>>>>> The following block should provide the commands to disable the foreign
>>>>> key pointing on a table. It works wonderfully in 11.2.0.4 and 12.1.0.2 but
>>>>> not on 12.2.0.1. Does not trigger an error but also no results. You can
>>>>> test it, just replace 'MYTABLE' with a table that has foreign key pointing
>>>>> on it.
>>>>>
>>>>> DECLARE
>>>>> -- table that has Foreignkey pointing on it
>>>>> v_tbl_name VARCHAR2(30) := 'MYTABLE';
>>>>> CURSOR get_massdata_tableinfo
>>>>> IS
>>>>> SELECT v_tbl_name table_name FROM dual
>>>>>
>>>>> ;
>>>>> CURSOR get_fks(par_target_table user_tables.table_name%TYPE)
>>>>> IS
>>>>> WITH
>>>>> user_constr AS
>>>>> (
>>>>> SELECT *
>>>>> FROM all_constraints
>>>>> WHERE owner = sys_context('USERENV', 'CURRENT_SCHEMA')
>>>>> )
>>>>> SELECT r.constraint_name,
>>>>> r.table_name
>>>>> FROM user_constr r,
>>>>> user_constr t
>>>>> WHERE t.table_name = par_target_table
>>>>> AND t.constraint_type = 'P'
>>>>> AND t.constraint_name = r.r_constraint_name
>>>>> ;
>>>>> BEGIN
>>>>> FOR crec IN get_massdata_tableinfo
>>>>> LOOP
>>>>> --
>>>>> dbms_output.put_line('Table Name ' || crec.table_name);
>>>>> -- disable FK´s pointing to table
>>>>> FOR rec IN get_fks(crec.table_name) --no rows in 12.2.0.1 (but
>>>>> it works in 11.2.0.4 and 12.1.0.2)
>>>>> LOOP
>>>>> dbms_output.put_line('ALTER TABLE ' || rec.table_name ||
>>>>> ' DISABLE CONSTRAINT ' || rec.constraint_name);
>>>>>
>>>>> END LOOP;
>>>>> END LOOP;
>>>>>
>>>>> END;
>>>>>
>>>>> If I call the SQL directly, then I get records:
>>>>>
>>>>> WITH
>>>>> user_constr AS
>>>>> (
>>>>> SELECT *
>>>>> FROM all_constraints
>>>>> WHERE owner = sys_context('USERENV', 'CURRENT_SCHEMA')
>>>>> )
>>>>> SELECT r.constraint_name,
>>>>> r.table_name
>>>>> FROM user_constr r,
>>>>> user_constr t
>>>>> WHERE t.table_name = 'MY_TABLE'
>>>>> AND t.constraint_type = 'P'
>>>>> AND t.constraint_name = r.r_constraint_name
>>>>>
>>>>> Is this a bug or have I just missed something?
>>>>>
>>>>> Regards
>>>>> Ahmed Fikri
>>>>>
>>>>>
>>>>> --
>>>>> http://www.freelists.org/webpage/oracle-l
>>>>>
>>>>>
>>>>>
-- http://www.freelists.org/webpage/oracle-lReceived on Tue Jan 29 2019 - 17:28:40 CET
