Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Unbeseitigbare Oracle-Sitzung wartet auf SQL*Net-Nachricht von Client-Ereignis

Dies scheint ein Fehler in Oracle zu sein, wenn CLOB Datentypen werden als Werte verwendet, die an MERGE übergeben werden -Anweisung ON Klausel. Angenommen diese Datenbank:

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

Wiedergabe mit eingebetteten Werten

Führen Sie nun die folgende Anweisung in einem beliebigen Oracle-Client aus, einschließlich SQL*Plus, SQL Developer oder von JDBC, wodurch das Problem sehr einfach reproduziert werden kann (ich verwende 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);

Das Beispiel ist albern, und der CLOB war hier "zufällig" gebunden. Trotzdem sollte eine solche Aussage keine Zombie-Session in Oracle erzeugen, aber sie ist da. Ich führe die obige Anweisung dreimal in SQL*Plus aus und führe dann dies aus...

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%';

... Ich bekomme:

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     

Beachten Sie, wie unterschiedlich das gemeldete Ereignis ist ("db file sequential read" ) aus dem ursprünglichen Ereignis ("SQL*Net-Nachricht vom Client"). ), die Bind-Variablen verwendete

Reproduktion unter Verwendung von Bindungswerten

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);

Die obige Anweisung, die in SQL*Plus ausgeführt wird, erzeugt ebenfalls den Fehler:

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

Keine Reproduktion in PL/SQL

Interessanterweise wird der Fehler in der folgenden PL/SQL-Anweisung vermieden:

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;
/

Ich bekomme:

          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

Es sieht so aus, als ob die PL/SQL-Engine Clients vor diesem SQL-Engine-Bug schützt.