Oracle
 sql >> база данни >  >> RDS >> Oracle

Неубиваема сесия на Oracle, чакаща SQL*Net съобщение от клиентско събитие

Това изглежда е грешка в Oracle, когато CLOB типовете данни се използват като стойности, които се предават на MERGE оператор ON клауза. Да приемем тази база данни:

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

Възпроизвеждане с помощта на вградени стойности

Сега изпълнете следния оператор във всеки клиент на Oracle, включително SQL*Plus, SQL Developer или от JDBC, което помага за много лесно възпроизвеждане на проблема (използвам 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);

Примерът е глупав и CLOB беше обвързан тук от "случайност". Въпреки това подобно изявление не трябва да създава зомби сесия в Oracle, но е там. Изпълнявам горния израз три пъти в SQL*Plus и след това изпълнявам това...

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

... Получавам:

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     

Забележете как докладваното събитие е различно („последователно четене на db файл“ ) от оригиналното събитие („SQL*Net съобщение от клиент“ ), който използва свързващи променливи

Възпроизвеждане чрез свързващи стойности

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

Горният оператор, изпълняван в SQL*Plus, също създава грешка:

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

Няма възпроизвеждане в PL/SQL

Интересното е, че грешката е избегната в следния 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;
/

Получавам:

          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

Изглежда, че PL/SQL машината предпазва клиентите от тази грешка в SQL машината.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Потребителят на схемата на Oracle не може да създаде таблица в процедура

  2. Грешка на Oracle ORA-28759:грешка при отваряне на файл при заявка на utl_http пакет

  3. изтриване на изявление без изтриване на записи

  4. Как да четем и съхраняваме XML данни в база данни

  5. Грешки при инсталиране на jdk 1.7 в linux