programing

장기간 실행 중인 데이터베이스 작업을 취소하는 방법은 무엇입니까?

oldcodes 2023. 6. 13. 22:46
반응형

장기간 실행 중인 데이터베이스 작업을 취소하는 방법은 무엇입니까?

현재 Oracle과 함께 작업 중이지만 MS SQL용 솔루션도 필요합니다.

저는 사용자가 데이터베이스에서 실행될 SQL을 생성할 수 있는 GUI를 가지고 있습니다.이 작업은 생성되는 검색에 따라 매우 오랜 시간이 걸릴 수 있습니다.이 검색 중에 GUI/App이 응답하고 사용자가 검색을 취소할 수 있도록 합니다.

백그라운드 작업자 스레드를 사용하고 있습니다.

문제는 사용자가 검색을 취소할 때 데이터베이스 호출을 중단할 수 없다는 것입니다.완료될 때까지 기다린 다음 '취소 보류 중' 속성을 폴링할 수 있습니다.이것은 데이터베이스의 리소스를 낭비할 뿐만 아니라 내 코드에 문제를 일으킵니다.

사용자가 매우 긴 쿼리에서 '검색'을 누른 후 '취소'를 누른 후 다시 '검색'을 누르면 첫 번째 검색이 계속 데이터베이스에서 삭제됩니다.다시 검색을 실행해도 백그라운드 작업자는 여전히 사용 중입니다.이 문제에 대한 유일한 해결책은 새로운 배경 작업자를 만드는 것입니다.

그것은 일을 하는 정말 추악한 방법처럼 보입니다.데이터베이스가 계속 작동합니다. 백그라운드 작업자의 새 인스턴스를 만들고 있습니다.데이터베이스 호출을 중지하고 동일한 작업자를 다시 사용하고 싶을 때.

내가 어떻게 그럴 수 있을까?

ADO.NET 및 SQL 데이터 공급자를 사용하는 경우 SqlCommand를 살펴보십시오.메서드를 취소합니다.그게 바로 당신이 찾고 있는 것입니다.하지만 취소를 시도하고 취소에 시간이 걸릴 수 있습니다.기본적으로 취소 요청을 언제 승인할지는 SQL Server에 달려 있습니다.쿼리가 취소되면 사용자가 작업을 취소했음을 나타내는 SqlException이 표시됩니다.분명히 이 예외를 예외로 취급하고 SqlException이 사용자의 작업 취소로 인해 발생하는 경우처럼 이 예외를 특별히 처리하고 싶지는 않습니다. 그냥 삼키면 됩니다.

명령어도 알아챘어요.취소()는 명령을 중단하지 않습니다.제게 도움이 된 것은 사용자가 중단할 때 연결(사용자가 연결을 사용할 경우 롤백 트랜잭션)을 닫는 것입니다.이렇게 하면 명령이 실행되는 동안 백그라운드 스레드에 예외가 발생하므로 이 예외를 포착하여 해당 취소 보류 속성을 확인하고 이 경우 예외를 다시 던지지 않아야 합니다.

// When aborting
worker.CancelAsync();
command.Connection.Close();

// In your DoWork event handler
...
catch (Exception)
{
    if (worker.CancellationPending)
    {
        e.Cancel = true;
        return;
    }
    else
    {
        throw;
    }
}

// And in your RunWorkerCompleted event handler
if (e.Error == null && !e.Cancelled)
{
    ...
}

가능하다고 확신합니다. Oracle용 TOD를 사용하면 여기에 설명된 것처럼 장기간 실행 중인 쿼리를 취소할 수 있습니다.근데 어떻게 하는지는 잘 모르겠어요.

백그라운드 작업자가 다른 스레드에서 실제 데이터베이스 호출을 실행하도록 한 다음 데이터베이스 호출이 완료되었는지 또는 취소가 눌러졌는지 정기적으로 확인하여 데이터베이스 스레드를 종료할 수 있습니다.이렇게 하면 실제로 데이터베이스가 로드되는 데 도움이 되지 않지만(쿼리가 전송되어 처리 중이기 때문에) 쿼리와 관련된 로컬 리소스를 해제할 수 있습니다.

가장 좋은 해결책은 모니터링 테이블을 통해 세션을 죽이는 것 같습니다.

Burnsys의 말처럼 오라클을 사용하면 성공할 수 있습니다.

Firebird 2.5에서는 동일하게 보입니다.

나는 Ms SQL에 비슷한 것이 있기를 바랍니다.

SQL Command를 사용하는 경우 Cancel 메서드라고 불러볼 수 있습니다.

데이터베이스에 대한 새 연결을 열고 sysdba로 로그인한 후 종료할 프로세스의 SID를 지정하는 "ALTER SYSTEM KILL SESSION 'sid,serial#' INMITED" 명령을 보내는 것은 어떻습니까?

세션 가져오기ID: v$sys에서 sid 선택(행 번호 = 1)

일련 번호를 가져오려면 sid, serial# from v$dll을 선택합니다. 여기서 sid = :SID

http://www.oracle-base.com/articles/misc/KillingOracleSessions.php

편집: 여기에서 sysdba로 로그인하지 않는 WW 아이디어: http://forums.oracle.com/forums/thread.jspa?threadID=620578

ADO 2.8과 SQLOLEDB 또는 SQL Server 네이티브 클라이언트에서 Cancel과 Close를 모두 사용해 보았습니다.취소를 사용하면 레코드 집합이 데이터 가져오기를 중지하지만 백그라운드에서 서버의 읽기가 계속되고 응용 프로그램의 메모리를 사용합니다.32비트 응용 프로그램에서는 몇 분 후에 "메모리 부족" 메시지가 표시될 수 있습니다.레코드 세트(또는 연결, 이전에 취소 여부와 상관없이)를 닫으면 ADO 2.8은 모든 레코드가 가져올 때까지 기다립니다.

ADO.NET이 더 나은지는 모르겠지만, ADO가 정말로 데이터 읽기를 중지하도록 Cancel/Close 후에 메모리와 네트워크 액세스를 모니터링하는 것이 좋을 것 같습니다.

KILL SESSION은 긴 실행 쿼리를 취소할 수 있는 유일한 방법이었습니다.제공된 관리 오라클 및 오라클 Command를 사용하고 있습니다.취소()가 작동할 때도 있지만 일반적으로 작동하지 않습니다.또한 Oracle Command.내 테스트에 따르면 명령 시간 초과가 허용되지 않습니다.얼마 전 관리되지 않는 오라클을 사용할 때 명령을 취소할 수 있었지만 관리되는 오라클에서는 더 이상 취소할 수 없었습니다.어쨌든 세션을 죽이는 것이 유일한 선택이었습니다.쿼리가 UI 스레드에서 실행되고 있지 않고 별도의 스레드에서 실행되고 있습니다.취소 명령은 UI 스레드에서 전송됩니다.응용 프로그램이 WCF를 사용하는 중간자를 사용하기 때문에 조금 더 복잡하지만 결국에는 세션을 종료하고 있습니다.물론 쿼리를 실행할 때 필요하면 세션을 찾아서 저장해야 합니다.오라클 세션을 죽이기 위해 sid와 serial#을 찾는 방법은 여러 가지가 있으며 이미 알고 있는 것을 설명하는 데 시간을 낭비하고 싶습니다.

Oracle 도입ALTER SYSTEM CANCEL SQL18세기에당신은 당신의 SQL에 UID가 있는 코멘트를 추가하고 다음과 같은 것을 찾아야 할 것입니다.

SELECT S.SID||','||S.SERIAL#
                    FROM GV$SESSION S, V$SQL Q
                    WHERE S.USERNAME IS NOT NULL
                    AND S.STATUS = 'ACTIVE'
                    AND S.SQL_ID IS NOT NULL
                    AND Q.SQL_ID = S.SQL_ID
                    and sql_text like '%{queryId}%'

그런 다음 .NET에서 다른 작업을 실행합니다.ALTER SYSTEM CANCEL SQL 'SID, SERIAL'

저는 그것이 가능하다고 생각하지 않습니다.다음은 Oracle 웹 사이트에서 이 주제에 대해 논의하는 링크입니다. http://forums.oracle.com/forums/thread.jspa?threadID=400492&start=15&tstart=0

언급URL : https://stackoverflow.com/questions/889102/how-to-cancel-a-long-running-database-operation

반응형