Oacle commt 와 rollback

8699 단어 oracle 학습
레 도 에 관 한 것 부터 살 펴 보 자.
      redo 벡터 는 redo 로그 파일 에 기록 되 어 있 습 니 다. Oacle 에서 로그 파일 을 사용 하 는 목적 은 미디어 오류 일 때 데이터 베 이 스 를 복원 할 수 있 습 니 다.Oacle 에는 온라인 로그 파일 과 압축 파일 로그 파일 두 가지 로그 파일 이 있 습 니 다.데이터베이스 마다 최소한 두 개의 로그 파일 이 있 습 니 다. 로그 파일 이 가득 찼 을 때 Oacle 은 다음 로그 파일 로 전환 하여 계속 씁 니 다. 이 때 로그 가 다시 가득 찼 을 때 Oacle 에서 압축 파일 로 그 를 사용 하지 않 으 면 Oacle 은 원래 의 일 지 를 덮어 쓰 고 1 번 로그 파일 을 다시 씁 니 다.Oacle 에서 압축 파일 로 그 를 사용 하면 Oacle 은 먼저 1 번 로 그 를 압축 파일 로그 에 기록 한 다음 로 그 를 기록 합 니 다.다음은 Oacle 공식 문서 의 설명 입 니 다. 여기 서 번역 하지 않 겠 습 니 다.
 
Redo entries record data that you can use to reconstruct all changes made to the database, including the undo segments. Therefore, the redo log also protects rollback data. When you recover the database using redo data, the database reads the change vectors in the redo records and applies the changes to the relevant blocks.
Redo records are buffered in a circular fashion in the redo log buffer of the SGA and are written to one of the redo log files by the Log Writer (LGWR) database background process. Whenever a transaction is committed, LGWR writes the transaction redo records from the redo log buffer of the SGA to a redo log file, and assigns a system change number (SCN) to identify the redo records for each committed transaction. Only when all redo records associated with a given transaction are safely on disk in the online logs is the user process notified that the transaction has been committed.
Redo records can also be written to a redo log file before the corresponding transaction is committed. If the redo log buffer fills, or another transaction commits, LGWR flushes all of the redo log entries in the redo log buffer to a redo log file, even though some redo records may not be committed. If necessary, the database can roll back these changes.
  
    commt 에 관 한 일 들:
        트 랜 잭 션 의 크기 가 얼마 든 간 에 commt 는 매우 빠 른 동작 입 니 다.때때로 우 리 는 매우 큰 일이 commt 에 있 을 때 매우 느 릴 것 이 라 고 생각한다.많은 개발 자 들 은 commt 의 작은 사무 가 큰 사 무 를 제출 하 는 것 보다 더 적은 시스템 자원 을 차지 할 것 이 라 고 생각 하지만 실제로 이런 방법 은 시스템 자원 의 소 모 를 증가 시 키 는 것 이다.적당 할 때 사 무 를 제출 합 니 다 (예 를 들 어 업무 가 모두 완료 되 었 습 니 다). 성능 을 향상 시 킬 뿐만 아니 라 공유 자원 의 경쟁 도 줄 일 수 있 습 니 다 (로그 파일, 많은 내부 latch 등).다음은 관련 된 예 를 보 겠 습 니 다.
 
SQL> create table t (x int);          

    。          

SQL> set serveroutput on
SQL> DECLARE
  2      l_start number default dbms_utility.get_time;         
  3     BEGIN
  4        for i in 1..10000         
  5        loop         
  6          INSERT INTO t VALUES(i);         
  7        end loop;         
  8        COMMIT;         
  9       dbms_output.put_line( dbms_utility.get_time-l_start || ' hsecs' );         
 10     END;         
 11     /         
32 hsecs
SQL> DECLARE
  2      l_start number default dbms_utility.get_time;         
  3     BEGIN
  4        for i in 1..10000         
  5        loop         
  6          INSERT INTO t VALUES(i);         
  7          COMMIT;         
  8        end loop;         
  9       dbms_output.put_line( dbms_utility.get_time-l_start || ' hsecs' );         
 10     END;         
 11       /         
67 hsecs         

PL/SQL        。

   우 리 는 끊임없이 업 무 를 제출 하 는 것 을 볼 수 있 습 니 다. 업무 가 끝 난 후에 제출 하 는 것 보다 시간 이 많이 걸 리 기 때문에 빈번 한 제출 을 사용 하지 않 아 도 시스템 자원 의 경쟁 을 줄 일 수 있 습 니 다.
    그런데 왜 commt 는 매우 빠 릅 니까? commt 전에 Oacle 은 99% 의 일 을 완 성 했 고 commt 는 해 야 할 일이 매우 적 기 때 문 입 니 다.다음은 Oacle 이 commt 전에 완 성 된 것 입 니 다.
  •  SGA 에서 생존 스크롤 백 기록 
  •  SGA 에서 수 정 된 데이터 블록 생 성
  • SGA 에서 상기 두 기록 의 재 작성 로그 기록 생 성
  • 상기 기록 의 크기 에 따라 상기 기록 의 조합 은 디스크 에 삭 제 됩 니 다
  • 모든 관련 자 물 쇠 를 획득 

  • 우리 가 commt 명령 을 내 렸 을 때, Oacle 은 다음 과 같은 일 을 했다.
  • 현재 사무 에 scn 번호 생 성
  • LGWR 은 남 은 로그 정 보 를 디스크 에 저장 합 니 다. transaction entry 가 제거 되 고 V $TRANSACTION 의 관련 기록 이 사라 집 니 다
  • 방출 된 모든 자물쇠 자원.
  • 모든 수 정 된 BUFFER CACHE 의 데이터 블록 은 clean 으로 표 시 됩 니 다. 즉, 다른 사무 가 이 데이터 블록 의 내용 을 덮어 쓸 수 있 습 니 다.

  •  
    그래서 위 를 통 해 알 수 있 듯 이 commt 는 해 야 할 일이 많 지 않다.그 중 가장 긴 동작 은 LGWR 을 실행 하여 로 그 를 디스크 에 긁 는 것 이다.그러나 LGWR 이 차지 하 는 시간 도 매우 제한 되 어 있 습 니 다. 사실 제출 하기 전에 로 그 를 다시 만 드 는 대부분의 사람들 이 디스크 에 반복 적 으로 긁 혔 습 니 다. 그러면 제출 업무 가 redo 를 디스크 에 긁 어서 많은 시간 을 소모 하 는 것 을 피 할 수 있 습 니 다.redo 가 다음 조건 을 만족 시 킬 때 Oacle 은 redo 를 디스크 에 표시 합 니 다.
     
  • 3 초 간격 으로 
  • redo 가 buffer 의 3 분 의 1 에 이 르 렀 을 때
  • commt 명령 을 내 린 후.

  •  
    우 리 는 예 를 들 어 commt 가 매우 부 드 러 운 조작 임 을 증명 합 니 다.
     
    SQL> create table t as select *  from all_objects;     
    
        。
    

     
    SQL> insert into t select * from t;     
    
       74429 。     
    
    SQL> insert into t select * from t;     
    
       148858 。     
    
    SQL> commit;
    

     
    CREATE OR REPLACE PROCEDURE DO_COMMIT(P_ROWS IN NUMBER) AS
      L_START       NUMBER;    
      L_AFTER_REDO  NUMBER;    
      L_BEFORE_REDO NUMBER;    
    BEGIN
      SELECT V$MYSTAT.VALUE    
        INTO L_BEFORE_REDO    
        FROM V$MYSTAT, V$STATNAME    
       WHERE V$MYSTAT.STATISTIC# = V$STATNAME.STATISTIC#    
         AND V$STATNAME.NAME = 'redo size';    
    
      L_START := DBMS_UTILITY.GET_TIME;    
      INSERT INTO T    
        SELECT * FROM T WHERE ROWNUM < P_ROWS;    
      DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' rows created');    
      DBMS_OUTPUT.PUT_LINE('Time to INSERT: ' || TO_CHAR(ROUND((DBMS_UTILITY.GET_TIME - L_START) / 100,5),'999.99') || ' seconds');    
      L_START := DBMS_UTILITY.GET_TIME;    
      COMMIT;    
      DBMS_OUTPUT.PUT_LINE('Time to COMMIT: ' || TO_CHAR(ROUND((DBMS_UTILITY.GET_TIME - L_START) / 100,5),'999.99') || ' seconds');    
    
      SELECT V$MYSTAT.VALUE    
        INTO L_AFTER_REDO    
        FROM V$MYSTAT, V$STATNAME    
       WHERE V$MYSTAT.STATISTIC# = V$STATNAME.STATISTIC#    
         AND V$STATNAME.NAME = 'redo size';    
    
      DBMS_OUTPUT.PUT_LINE('Generated ' ||TO_CHAR(L_AFTER_REDO - L_BEFORE_REDO,'999,999,999,999') || ' bytes of redo');    
      DBMS_OUTPUT.NEW_LINE;    
    END;
    

    지금 우 리 는 상술 한 과정 을 호출 합 니 다.
    SQL>    BEGIN
      2    FOR I IN 1 .. 5 LOOP    
      3      DO_COMMIT(POWER(10, I));    
      4    END LOOP;    
      5  END
      6  ;    
      7  /    
    9 rows created    
    Time to INSERT:    3.45 seconds    
    Time to COMMIT:     .00 seconds    
    Generated            2,484 bytes of redo    
    
    99 rows created    
    Time to INSERT:     .03 seconds    
    Time to COMMIT:     .00 seconds    
    Generated            9,356 bytes of redo    
    
    999 rows created    
    Time to INSERT:     .24 seconds    
    Time to COMMIT:     .00 seconds    
    Generated          103,336 bytes of redo    
    
    9999 rows created    
    Time to INSERT:    1.15 seconds    
    Time to COMMIT:     .00 seconds    
    Generated        1,052,000 bytes of redo    
    
    99999 rows created    
    Time to INSERT:    6.31 seconds    
    Time to COMMIT:     .00 seconds    
    Generated       11,500,372 bytes of redo    
    
    
    PL/SQL        。
    
    SQL> show parameter log_buffer;    
    
    NAME                                 TYPE        VALUE    
    ------------------------------------ ----------- ---------------    
    log_buffer                           integer     8593408
    

    이 를 통 해 알 수 있 듯 이 트 랜 잭 션 이 생 성 된 redo 가 아무리 크 더 라 도 commt 는 사용 하 는 시간 이 짧 습 니 다. redo 가 cache 의 3 분 의 1 에 이 르 렀 을 때 lgwr 는 배경 에서 redo 를 디스크 에 칠 하기 때문에 제출 할 때 나머지 redo 가 많 지 않 기 때문에 redo 가 commt 에 미 치 는 영향 은 매우 적 습 니 다.
     
    rollback 에 관 한 것들:
    위의 이 사례 에 대해 만약 에 우리 가 commt 를 rollback 으로 바 꾸 면 어떻게 될 까?
    9 rows created 
    Time to INSERT:     .00 seconds 
    Time to ROLLBACK:     .00 seconds 
    Generated            1,384 bytes of redo 
    
    99 rows created 
    Time to INSERT:     .00 seconds 
    Time to ROLLBACK:     .00 seconds 
    Generated            9,768 bytes of redo 
    
    999 rows created 
    Time to INSERT:     .03 seconds 
    Time to ROLLBACK:     .00 seconds 
    Generated          108,052 bytes of redo 
    
    9999 rows created 
    Time to INSERT:     .09 seconds 
    Time to ROLLBACK:     .02 seconds 
    Generated        1,106,744 bytes of redo 
    
    99999 rows created 
    Time to INSERT:     .87 seconds 
    Time to ROLLBACK:     .03 seconds 
    Generated       12,208,564 bytes of redo 
    
    
    PL/SQL        。
    

    따라서 업무 의 크기 가 rollback 에 미 치 는 영향 이 비교적 크다 는 것 을 알 수 있 습 니 다. 이 유 는 Oacle 이 rollback 복원 전의 모든 작업 을 완성 하여 데이터 베 이 스 를 일치 하 는 상태 로 복원 해 야 하기 때 문 입 니 다. 。rollback 이후 Oacle 은 다음 과 같은 작업 을 수행 해 야 합 니 다.
  • undo 세그먼트 의 정 보 를 읽 고 이전 모든 작업 에 역 작업 을 합 니 다. 예 를 들 어 insert 를 실 행 했 으 면 이때 delete 를 실행 해 야 합 니 다.
  • 모든 자 물 쇠 를 방출 한다.

  • rollback 은 데이터베이스 자원 을 소모 하 는 일 임 을 알 수 있 기 때문에 Oacle 에 서 는 일반적으로 비교적 큰 업무 에서 rollback 을 사용 하지 않 습 니 다.

    좋은 웹페이지 즐겨찾기