>source

오라클 드라이버를 사용하여 데이터베이스 업데이트를 수행하는 간단한 프로그램이 있습니다. SQLDeveloper 모드에서 작동하지만 Java 프로그램에서 실행이 중단되는 장기 실행 SQL입니다.

String sql= "UPDATE ...";
PreparedStatement ps= conn.prepareStatement(sql);
log.info(sql);
int affectedRows= ps.executeUpdate();
log.info("affected rows= " + affectedRows);

SQL 행을 기록하지만 영향을 받는 행 행은 인쇄하지 않습니다.

데이터베이스에서 실행(V$SESSION_LONGOPS)은(는) 남은 시간이 0인 상태에서 완료됩니다.

하지만 이상한 점은 이 세션이V$SESSION_LONGOPS하지만V$SESSION. 그리고 분명히 이것은 Java 프로그램으로 돌아 가지 않습니다. 프로그램의 실행 시스템에서,ps -ef이 정보를 제공합니다:

user 5889  5885  0 00:00 ?        00:00:11 /java/jdk1.6.0_25/bin/java -cp ...

00.00(Cron에서 예약)에 실행을 시작하여 11초 동안만 실행되었음을 보여줍니다(현재 10시간이 지난 오전 10시입니다). 프로그램이 멈추거나 죽는 것처럼 보이며 로그에 예외가 제공되지 않습니다(큰 try catch는 로그 예외로 둘러싸여 있음).

ps는 여전히 이것을 인쇄하고 다음 줄의 로그가 없기 때문에 프로그램의 끝에 도달하지 않습니다.

방향을 알려주는 도움을 주시면 감사하겠습니다.

처음에는 데이터베이스 세션이 어떻게든 연결이 끊어진 것처럼 보입니다.

Bob Jarvis - Reinstate Monica2021-09-20 03:58:59

@BobJarvis 나는 같은 것을 의심하지만 예외는 없습니다.

texasbruce2021-09-20 03:58:59

세션이 서버 측에서 삭제되었거나 네트워크 문제가 있는 경우 Java 측에서 시간 초과가 길고 아직 눈치채지 못했을 가능성이 있습니다. SQL*Net 로그의 서버 경고 로그에 문제를 나타내는 내용이 있습니까? (또한 11초는 현재까지 해당 Java 프로세스의 총 CPU 시간이며 경과된 실시간이 아니며 별도의 프로세스에서 처리하므로 데이터베이스의 CPU 시간은 포함하지 않습니다.)

Alex Poole2021-09-20 03:58:59

@AlexPoole 도움 감사합니다! 아직 살아 있는 아주 오래된 트랜잭션을 찾았습니다... 세션이 longops 테이블에 표시되지 않지만 여전히 살아 있다는 사실에 놀랐습니다!

texasbruce2021-09-20 03:58:59

커밋되지 않은 변경으로 인해 오래된 트랜잭션이 차단되거나 차단되고 있습니까? 아마도 어딘가에서 수동으로 업데이트를 시도하고 롤백하지 않고 해당 세션을 활성 상태로 두는 것입니까? 액세스 권한이 있는 경우 dba_waiters 및 dba_blockers 보기를 살펴보십시오. 실제로 반환되는 모든 것을 이해하려면 세션 정보가 필요합니다.

Alex Poole2021-09-20 03:58:59
  • 답변 # 1

    나는 같은 문제가 있었다. executeUpdate가 중단되었고 오류가 없었습니다.

    문제: 같은 db에 sqlDeveloper와 동시에 연결되어 있었고 같은 테이블이 열려 있었습니다. DB에서 sqlDeveloper의 연결을 끊는 즉시 명령문을 삽입할 수 있습니다. Java 응용 프로그램은 계속 잘 작동했습니다.

  • 답변 # 2

    저도 당신과 같은 문제를 겪었습니다. 다른 분들은 모르겠는데 그냥 SQLplus를 닫아서 해결했습니다! sqlplus가 콘솔에서 실행되는 동안 일부 쿼리가 작동했기 때문에 해결할 수 있다고 생각하지 않았지만 닫았고 이제 모든 쿼리가 작동하고 아무 것도 멈춥니다!

    문제가 있는 경우 시도해 볼 수 있습니다!

    나는 Oracle 데이터베이스를 사용하고 있으며 또한 열어 두었습니다. 그것을 닫으면 내 실행도 허용되었습니다. 감사합니다.

    user79388602021-09-20 19:06:11
  • 답변 # 3

    요약:

    1. SQL에서 시간 초과 설정
    2. 시간 초과 후에도 업데이트가 여전히 유효하고 행이 변경되었는지 확인합니다.
    3. VisualVM 및 디버거를 사용하여 드라이버가 클라이언트에서 수행하는 작업 확인

    응용 프로그램이 무엇을 하는지 확인해야 합니다. 먼저 실행하려는 명령문의 Timeout을 설정할 수 있습니다. 20초로 설정하면 클라이언트 측에서 간단히 SQLTimeoutException을 생성할 수 있습니다.

    try {} catch(SQLTimeoutException e) {}를 사용하여 알림을 인쇄할 수 있습니다. 다음으로 SQL이 실행되었는지 여부를 확인하는 문을 만들 수 있습니다.

    일반적인 SQL Developer 타이밍은 무엇이며 왜 그렇게 오래 걸리나요? SQL과 테이블 구조를 알려주실 수 있나요? 모든 트리거, 보기 또는 구체적인 테이블을 업데이트합니까?

    다음으로 할 수 있는 일은 VisualVM을 사용하고 SQL이 중단되는 동안 스레드 덤프를 만드는 것입니다. 제한 시간을 60초로 늘리고 ThreadDump를 만듭니다. 거기에서 스레드가 수행하는 작업과 Oracle 드라이버가 실제로 데이터베이스가 응답하기를 기다리는 것보다 소켓 연결을 기다리는 경우를 볼 수 있습니다. 다른 행동을 보면 무슨 일이 일어나고 있는지 짐작할 수 있습니다.

    또 다른 아이디어는 디버그 모드에서 애플리케이션을 실행하는 것입니다. 30초(타임아웃은 여전히 ​​60초) 동안 기다렸다가 애플리케이션을 일시 중지하고 연결을 관리하는 스레드를 확인합니다. 그는 어디서 무엇을 하고 있는 걸까. 내가 올바르게 기억한다면 오라클 드라이버의 소스를 선택할 수 있습니다. JD 또는 이와 유사한 것을 사용하여 code를 디컴파일하거나 바이트 code를 읽는 것이 아니라면... .

  • 답변 # 4

    세션이 대기 모드인지 여부를 아래 표에서 확인할 수 있습니다.

    dba_blockers에서 * 선택; dba_waiters에서 *를 선택하십시오.

    세션이 위 쿼리에 없는지 확인하십시오.

    또한 아래 쿼리로 개체가 잠겨 있지 않은지 확인하십시오.

    이 보기의 v$locked_object에서 *를 선택하면 잠긴 개체 ID를 얻을 수 있고 dba_objects에서 개체 이름을 얻을 수 있습니다.

    이 세션에서 세션을 찾으면 먼저 해당 세션을 종료하거나 종료하십시오.

  • 이전 initMap은 Google Maps Javascript 기능이 아닙니다.
  • 다음 데이터베이스 업데이트 시 System.Resources.MissingManifestResourceException