Delphi+Oracle сброс сессий в Oracle

denkira
Дата: 04.11.2019 02:07:49
Всем привет, пишу себе упрощалку для сброса сессий в Oracle, блокируется запись в таблице и ее необходимо скидывать. Стандартно это делаю через апдейт таблицы и сброс сессии:

select 'alter system kill session '''||b.SID||','||b.SERIAL#||''''||' immediate;'
from v$session s, v$session b where s.status='ACTIVE' and s.EVENT like 'enq%' 
and s.seconds_in_wait>1
and s.blocking_session=b.sid
order by b.sid, s.sid


Хотел бы реализовать на Delphi:
1) беру в отдельном потоке таблицу на апдейт
2) скидываю ее по щелчку второй кнопки

Но увы почему-то не скидывается
На форме два ADOQuery один делает соответственно апдейт, а вот второй не хочет скидывать сессию, просто висит


Содержимое ADOQuery: (запрос в девелопере скидывает сессию, а вот через Делфи не фига)

declare
begin
    for ss in (
    select b.SID, b.SERIAL#
      from v$session s, v$session b, V$SQL sq
     where s.status = 'ACTIVE'
       and s.EVENT like 'enq%'
       and s.seconds_in_wait > 1
       and s.blocking_session = b.sid
       and s.SQL_ADDRESS=sq.ADDRESS
       and SQL_TEXT like '%--#@$rE3df%^!!%' 
    )
    loop
        execute immediate 'alter system kill session ''' || to_char(ss.sid,'999999')
                                   || ',' ||to_char(ss.serial#,'999999')||'''';
        commit;
    end loop;
end;

Вызываю его: Form1.ADOQuery2.ExecSQL;
Поток работает нормально, блокировка появляется.
Помогите советом =)

Модератор: Пользуйтесь тегом (кнопкой) SRC для оформления кода, пожалуйста.
Кроик Семён
Дата: 04.11.2019 11:55:48
denkira
2) скидываю ее по щелчку второй кнопки


вот этот момент непонятен :)
Кроик Семён
Дата: 04.11.2019 13:58:49
кстати, из-под какого юзера работает ADOQuery? Случаем он не сам себя прибивает?
Кроик Семён
Дата: 04.11.2019 14:04:38
и еще, зачем commit в запросе?
ma1tus
Дата: 04.11.2019 15:55:14
denkira
, просто висит

Specify IMMEDIATE to instruct Oracle Database to ... return control to you immediately.
?
denkira
Дата: 05.11.2019 04:01:40
Кроик Семён
denkira
2) скидываю ее по щелчку второй кнопки


вот этот момент непонятен :)


Форма на ней едит и кнопка, вводишь номер айдишника строки таблицы которую держит на апдейте кто-то, нажимаешь кнопку и он скидывает пользователя с апдейта.



Кроик Семён
кстати, из-под какого юзера работает ADOQuery? Случаем он не сам себя прибивает?


Все под одним юзером с правами у него все хорошо, прибить он сам себя не может, так как запрос на сброс сессий тащит сид пользователя, а не мой. (Девелопер хавает запрос, и сессию убивает, ставил эксперимент перед переносом в Делфи) комит уберу.


ma1tus
denkira
, просто висит

Specify IMMEDIATE to instruct Oracle Database to ... return control to you immediately.
?


Ошибок нет, просто висит, запускал по отдельности ADOQuery работают нормально, но вместе дружить не хотят (По отдельности это на апдейт таблицу берет и появляется блокировка, но вот когда до момента сброса доходит, то тут висит, так же если наоборот и в девелоперский искусственно сделать блокировку, то он убивает)
Александр Спелицин
Дата: 05.11.2019 12:48:07
1. Вы через одно соединение пытаетесь сделать и блокировку таблицы и принудительное завершение текущей сессии.
Если обе вещи дошли до Oracle, то Вы должны получить ошибку ORA-00027.
2. Затык может быть на уровне ADOConnection , который не пропускает 2-ю команду, не дождавшись полного выполнения (в т.ч. и снятия блокировок) 1-й.

Исключите из Вашего курсора запись, соответствующую текущей сессии.
denkira
Дата: 06.11.2019 11:15:32
Александр Спелицин

1. Вы через одно соединение пытаетесь сделать и блокировку таблицы и принудительное завершение текущей сессии.
Если обе вещи дошли до Oracle, то Вы должны получить ошибку ORA-00027.
2. Затык может быть на уровне ADOConnection , который не пропускает 2-ю команду, не дождавшись полного выполнения (в т.ч. и снятия блокировок) 1-й.

Исключите из Вашего курсора запись, соответствующую текущей сессии.



1) Про одно соединение понял, запихнул два ADOConnection, для каждого запроса.
2) "Исключите из Вашего курсора запись, соответствующую текущей сессии" - не понял, что конкретно убрать и зачем.

Даже две конекции не помогли:

unit TPN_Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, DBGrids, ADODB, DB, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
    Button2: TButton;
    ADOQuery2: TADOQuery;
    Button3: TButton;
    ADOConnection2: TADOConnection;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyThread = class(TThread)
    private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;
  MyThread: TMyThread;
  i:integer;
  sql_:string;
implementation

{$R *.dfm}



//Поток
procedure TMyThread.Execute;
begin

 Form1.ADOQuery1.ExecSQL;

end;



procedure TForm1.Button1Click(Sender: TObject);
begin

//Создаем экземпляр потока:
MyThread:=TMyThread.Create(False);
//Параметр False запускает поток сразу после создания, True - запуск впоследствии , методом Resume
//Указываем приоритет потока
MyThread.Priority:=tpNormal;


Form1.ADOQuery2.ExecSQL;

end;

end.
denkira
Дата: 07.11.2019 19:51:11
С убийством сессии вроде разобрался (был неверный курсор на убийство сессии, поправил), хотел бы спросить как грамотно, в моем примере убивать выполнение потока и убирать таблицу с апдейта.


//Поток
procedure TMyThread.Execute;
begin
try

//Берем таблицу на апдейт
Form1.ADOQuery1.Active := false;
Form1.ADOQuery1.SQL.Clear;
sql_:='';
sql_:='select * from sys5.dka for update --#@$rE3df%^!!';
Form1.ADOQuery1.SQL.Add(sql_);
Form1.ADOQuery1.Active := True;


//Ошибка
except
   ShowMessage('Ошибка обработки потока!');
   Form1.ADOQuery1.Active:=false;
end;
end;


Как теперь убрать этот апдейт? (неужели и тут нужно делать kill sid)
softwarer
Дата: 08.11.2019 00:10:30
denkira
блокируется запись в таблице и ее необходимо скидывать.

Хм. Чёткий подход к взаимодействию. А в сортире если кабинка занята, стреляете сквозь дверь?

denkira
select 'alter system kill session '''||b.SID||','||b.SERIAL#||''''||' immediate;'

В сколько-нибудь современных версиях Oracle стоит использовать disconnect. У kill session на нагруженном сервере есть раздражающая привычка заканчивать выполнение часа через два.

denkira
На форме два ADOQuery

Работа с Oracle через ADO - удовольствие для приверженцев нетрадиционного секса.

denkira
один делает соответственно апдейт, а вот второй не хочет скидывать сессию, просто висит

Попробуй для начала вместо alter system выполнить там select * from dual. Думаю, Вы ещё и загоняете их в одну сессию.