sql >> Databáze >  >> RDS >> Oracle

Unkillable Oracle session čekající na SQL*Net zprávu z události klienta

Zdá se, že se jedná o chybu v Oracle, když CLOB datové typy se používají jako hodnoty, které se předávají do MERGE příkazu ON doložka. Předpokládejme, že tato databáze:

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

Reprodukce pomocí vložených hodnot

Nyní spusťte následující příkaz v libovolném klientovi Oracle, včetně SQL*Plus, SQL Developer nebo z JDBC, což pomáhá velmi snadno reprodukovat problém (používám 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);

Příklad je hloupý a CLOB byl zde svázán „náhodou“. Nicméně takové prohlášení by nemělo vytvořit zombie relaci v Oracle, ale je tam. Spouštím výše uvedený příkaz třikrát v SQL*Plus a pak spouštím toto...

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

... chápu:

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     

Všimněte si, jak se nahlášená událost liší ("sekvenční čtení souboru db" ) z původní události ("SQL*Net zpráva od klienta" ), který používal proměnné vazby

Reprodukce pomocí hodnot vazby

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

Výše uvedený příkaz spuštěný v SQL*Plus také vytváří chybu:

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

Žádná reprodukce v PL/SQL

Je zajímavé, že se této chybě vyhýbá následující příkaz PL/SQL:

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

Dostávám:

          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

Vypadá to, že PL/SQL engine chrání klienty před touto chybou SQL engine.




  1. Sekvence provádění klauzule Seskupit podle, Mít a Kde v SQL Server?

  2. Převést „smalldatetime“ na „datetime“ v SQL Server (příklady T-SQL)

  3. Problém Java + Mysql UTF8

  4. Co znamená Chyba importu:Symbol nenalezen:_PQencryptPasswordConn znamená a jak to mohu opravit?