sql >> Database >  >> RDS >> Oracle

Unkillable Oracle-sessie wacht op SQL*Net-bericht van clientgebeurtenis

Dit lijkt een bug te zijn in Oracle wanneer CLOB gegevenstypen worden gebruikt als waarden die worden doorgegeven aan de MERGE statement is ON clausule. Stel deze database:

CREATE TABLE t (
  v INT, 
  s VARCHAR2(400 CHAR)
);

Reproductie met inline-waarden

Voer nu de volgende instructie uit in een Oracle-client, inclusief SQL*Plus, SQL Developer of vanuit JDBC, waardoor het probleem heel gemakkelijk kan worden gereproduceerd (ik gebruik Oracle 11g XE 11.2.0.2.0):

MERGE INTO t                      
USING (
  SELECT 
    1 v, 
    CAST('abc' AS CLOB) s 
  FROM DUAL
) s 
ON (t.s = s.s) -- Using a CLOB here causes the bug.
WHEN MATCHED THEN UPDATE SET
  t.v = s.v        
WHEN NOT MATCHED THEN INSERT (v, s) 
VALUES (s.v, s.s);

Het voorbeeld is dwaas, en de CLOB was hier gebonden door "ongeluk". Desalniettemin zou zo'n statement geen zombiesessie in Oracle moeten creëren, maar het is er wel. Ik voer de bovenstaande instructie drie keer uit in SQL*Plus en voer vervolgens dit uit...

SELECT 
  s.sid,
  s.serial#,
  s.sql_id,
  s.event,
  s.blocking_session,
  q.sql_text
FROM v$session s
JOIN v$sql q
ON s.sql_id = q.sql_id
WHERE s.username = 'TEST'
AND UPPER(TRIM(q.sql_text)) LIKE 'MERGE%';

... ik krijg:

sid serial# sql_id          event                       blocking_session
9   3       82a2k4sqzy1jq   cursor: pin S wait on X     92
49  89      82a2k4sqzy1jq   cursor: pin S wait on X     92
92  13      82a2k4sqzy1jq   db file sequential read     

Merk op hoe de gerapporteerde gebeurtenis anders is ("db file sequentiële read" ) van de oorspronkelijke gebeurtenis ("SQL*Net-bericht van client" ), die bindvariabelen gebruikte

Reproductie met bindingswaarden

var v_s varchar2(50)
exec :v_s := 'abc'

MERGE INTO t                      
USING (
  SELECT 
    1 v, 
    CAST(:v_s AS CLOB) s 
  FROM DUAL
) s 
ON (t.s = s.s) -- Using a CLOB here causes the bug.
WHEN MATCHED THEN UPDATE SET
  t.v = s.v        
WHEN NOT MATCHED THEN INSERT (v, s) 
VALUES (s.v, s.s);

De bovenstaande instructie uitgevoerd in SQL*Plus produceert ook de bug:

sid serial# sql_id          event                           blocking_session
8   1       4w9zuxrumumgj   SQL*Net message from client     
90  7       4w9zuxrumumgj   cursor: pin S wait on X         8
94  21      4w9zuxrumumgj   cursor: pin S wait on X         8

Geen reproductie in PL/SQL

Interessant is dat de bug wordt vermeden in de volgende PL/SQL-verklaring:

DECLARE
  v_s CLOB := 'abc';
BEGIN
  MERGE INTO t                      
  USING (
    SELECT 
      1 v, 
      CAST(v_s AS CLOB) s 
    FROM DUAL
  ) s 
  ON (t.s = s.s) -- Using a CLOB here causes the bug.
  WHEN MATCHED THEN UPDATE SET
    t.v = s.v        
  WHEN NOT MATCHED THEN INSERT (v, s) 
  VALUES (s.v, s.s);
END;
/

Ik krijg:

          CAST(v_s AS CLOB) s
          *
ERROR at line 8:
ORA-06550: line 8, column 11:
PL/SQL: ORA-00932: inconsistent datatypes: expected - got CLOB
ORA-06550: line 4, column 7:
PL/SQL: SQL Statement ignored

Het lijkt erop dat de PL/SQL-engine klanten behoedt voor deze bug in de SQL-engine.




  1. Oracle Long Raw-probleem

  2. SQL-query om te sorteren en unieke telling te bereiken

  3. Hoe Acosh() werkt in PostgreSQL

  4. SQL-cast datum/tijd