Как проверить базу данных Oracle на наличие длительных запросов


99

Мое приложение, использующее базу данных Oracle, работает медленно или, похоже, полностью остановилось.

Как узнать, какие запросы самые дорогие, чтобы я мог продолжить изучение?

Ответы:


135

Это показывает SQL, который в настоящее время является «АКТИВНЫМ»: -

select S.USERNAME, s.sid, s.osuser, t.sql_id, sql_text
from v$sqltext_with_newlines t,V$SESSION s
where t.address =s.sql_address
and t.hash_value = s.sql_hash_value
and s.status = 'ACTIVE'
and s.username <> 'SYSTEM'
order by s.sid,t.piece
/

Это показывает замки. Иногда все идет медленно, но это потому, что он заблокирован в ожидании блокировки:

select
  object_name, 
  object_type, 
  session_id, 
  type,         -- Type or system/user lock
  lmode,        -- lock mode in which session holds lock
  request, 
  block, 
  ctime         -- Time since current mode was granted
from
  v$locked_object, all_objects, v$lock
where
  v$locked_object.object_id = all_objects.object_id AND
  v$lock.id1 = all_objects.object_id AND
  v$lock.sid = v$locked_object.session_id
order by
  session_id, ctime desc, object_name
/

Это хороший вариант для поиска длительных операций (например, полного сканирования таблицы). Если это из-за большого количества коротких операций, ничего не появится.

COLUMN percent FORMAT 999.99 

SELECT sid, to_char(start_time,'hh24:mi:ss') stime, 
message,( sofar/totalwork)* 100 percent 
FROM v$session_longops
WHERE sofar/totalwork < 1
/

1
Есть ли способ безопасно убить такие запросы, если они выполняются более x минут. Спасибо за ответ @UmberFerrule
TommyT

2
@TommyT Вы можете использовать, alter system kill sessionкак описано здесь: docs.oracle.com/cd/B28359_01/server.111/b28310/…
WW.

37

Попробуйте это, это даст вам запросы, которые в настоящее время выполняются более 60 секунд. Обратите внимание, что он печатает несколько строк для каждого выполняющегося запроса, если SQL имеет несколько строк. Посмотрите на sid, серийный номер, чтобы увидеть, что принадлежит друг другу.

select s.username,s.sid,s.serial#,s.last_call_et/60 mins_running,q.sql_text from v$session s 
join v$sqltext_with_newlines q
on s.sql_address = q.address
 where status='ACTIVE'
and type <>'BACKGROUND'
and last_call_et> 60
order by sid,serial#,q.piece

Я запускаю этот запрос, и он сообщает мне, что утверждение

Это действительно так. Я это тестировал. Какой инструмент вы используете для запроса? Возможно, его путают со знаком #. Попробуйте изменить начало и конец следующим образом: «select * from ... order by sid, q.piece»
Карлос А. Ибарра

2
Кроме того, вам необходимо запустить это с привилегированной учетной записью, имеющей доступ к v $ session, v $ sqltext_with_newlines
WW.

Это работает, но возвращает текст запроса SQL в очень странном формате.
Бернхард Дёблер 05

7

v $ session_longops

Если вы поищете sofar! = Totalwork, вы увидите те, которые не были завершены, но записи не удаляются после завершения операции, поэтому вы также можете увидеть там много истории.


Хороший намек. Также подробно обсуждается здесь .
dma_k

4
Step 1:Execute the query

column username format 'a10'
column osuser format 'a10'
column module format 'a16'
column program_name format 'a20'
column program format 'a20'
column machine format 'a20'
column action format 'a20'
column sid format '9999'
column serial# format '99999'
column spid format '99999'
set linesize 200
set pagesize 30
select
a.sid,a.serial#,a.username,a.osuser,c.start_time,
b.spid,a.status,a.machine,
a.action,a.module,a.program
from
v$session a, v$process b, v$transaction c,
v$sqlarea s
Where
a.paddr = b.addr
and a.saddr = c.ses_addr
and a.sql_address = s.address (+)
and to_date(c.start_time,'mm/dd/yy hh24:mi:ss') <= sysdate - (15/1440) -- running for 15 minutes
order by c.start_time
/   

Step 2: desc v$session

Step 3:select sid, serial#,SQL_ADDRESS, status,PREV_SQL_ADDR from v$session where sid='xxxx' //(enter the sid value)

Step 4: select sql_text from v$sqltext where address='XXXXXXXX';

Step 5: select piece, sql_text from v$sqltext where address='XXXXXX' order by piece;

1

Вы можете создать отчет AWR (автоматический репозиторий рабочей нагрузки) из базы данных.

Запустите из командной строки SQL * Plus:

SQL> @$ORACLE_HOME/rdbms/admin/awrrpt.sql

Прочтите документ о том, как создать и понять отчет AWR. Это даст полное представление о производительности базы данных и проблемах с ресурсами. Когда мы ознакомимся с отчетом AWR, будет полезно найти Top SQL, который потребляет ресурсы.

Кроме того, в пользовательском интерфейсе 12C EM Express мы можем сгенерировать AWR.


0

Вы можете проверить детали длительных запросов, такие как процент выполнения и оставшееся время, используя следующий запрос:

 SELECT SID, SERIAL#, OPNAME, CONTEXT, SOFAR, 
 TOTALWORK,ROUND(SOFAR/TOTALWORK*100,2) "%_COMPLETE" 
 FROM V$SESSION_LONGOPS 
 WHERE OPNAME NOT LIKE '%aggregate%' 
       AND TOTALWORK != 0 
       AND SOFAR <> TOTALWORK;

Полный список действий по устранению неполадок можно найти здесь: Устранение неполадок длительных сеансов


0
select sq.PARSING_SCHEMA_NAME, sq.LAST_LOAD_TIME, sq.ELAPSED_TIME, sq.ROWS_PROCESSED, ltrim(sq.sql_text), sq.SQL_FULLTEXT
  from v$sql sq, v$session se
 order by sq.ELAPSED_TIME desc, sq.LAST_LOAD_TIME desc;

0

Вы можете использовать представление v $ sql_monitor, чтобы найти запросы, которые выполняются дольше 5 секунд. Это может быть доступно только в корпоративных версиях Oracle. Например, этот запрос будет определять медленно выполняющиеся запросы из моей службы TEST_APP:

select to_char(sql_exec_start, 'dd-Mon hh24:mi'), (elapsed_time / 1000000) run_time,
       cpu_time, sql_id, sql_text 
from   v$sql_monitor
where  service_name = 'TEST_APP'
order  by 1 desc;

Обратите внимание, что elapsed_time находится в микросекундах, поэтому / 1000000, чтобы получить что-то более читаемое

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.