Database초보우낙

20. 파이썬으로 alert log file 분석하기 1 본문

파이썬

20. 파이썬으로 alert log file 분석하기 1

오운학 2024. 4. 17. 16:12

데이터 이행을 하게 되면 로그 스위치의 빈도수가 증가하게 되는데 리두로그 파일의 갯수가 작거나 크기가 작으면 로그 스위치가 빈번하게 발생하면서 database의 성능을 저하시키는 원인이 된다

즉 결론적으로 데이터 이행이 늦어지게 된다

그래서 평상시보다 로그 스위치의 빈도수가 얼마나 많은지 분석을 할 수 있도록 파이썬으로 alert log file을 다음과 같이 분석한다

 

 

 

 

문제1. 다음의 sql을 scott에서 수행해서 로그 스위치를 여러번 일으키세요

insert  into  emp(empno, ename, sal)  values( 1111,'jack', 3000);
commit;
alter  system  switch  logfile;

 

 

위의 sql을 3번 수행하는데 수행하기전에 별도의 터미널창을 열어서 alert log file 을 tail -f 로 모니터링해놓으세요.

 

로그스위치는 자동으로 발생하는데 로그 스위치의 빈도수가 많으면서 오라클의 성능이 느려지면 LGWR가 리두로그파일에 쓸때 상태가 ACTIVE여서 못써서 발생한 현상.

이 현상을 분석

 

문제2.  AI에게 alert log file에 맨 아래부분을 복사해서 붙여주고 로그 스위치의 간격 시간이 평균적으로 얼마나 되는지 분석해달라고 요청하세요

주어진 로그를 분석하여 로그 스위치의 간격을 계산해보았습니다. 주어진 로그에서 로그 스위치가 발생한 시간은 다음과 같았습니다:
첫 번째 로그 스위치: 12:03:20두 번째 로그 스위치: 12:09:11세 번째 로그 스위치: 12:11:09
이를 바탕으로 각 로그 스위치 사이의 간격을 계산한 결과는 다음과 같습니다:
첫 번째와 두 번째 로그 스위치 사이의 간격: 약 5분 51초두 번째와 세 번째 로그 스위치 사이의 간격: 약 1분 58초
이를 평균하면 약 3분 55초로, 로그 스위치의 평균 간격은 약 3분 55초입니다.

dba 모집 공고에 파이썬 활용이 가능한자라고 나오는 이유?

“데이터 파이프 라인 구축”

날것의(raw) 데이터가 입력이 되면 이 데이터 통계를 분석하는 사용자가 보기 좋은형태로 만들어줘야하는데 이 과정을 파이프 라인 구축이라고 합니다.

리눅스의 쉘 스크립트와 PL/SQL로 데이터를 가져오고 가공하는 코드를 다 구현하고 파이썬에서는 리눅스의 쉘스크립트를 호출해서 데이터를 화면에 보여주는 역활

문제3. 리눅스 명령어를 이용해서 alert log file에서 로그 스위치에 해당하는 그 라인을 출력하시오 !

##.bash_profile에 alias로 trace='cd /u01/app/oracle/diag/rdbms/orcl/orcl/trace'를 추가해줬다


[orcl:trace]$ grep -B 1 "(LGWR switch)" alert*


grep -B 1 "(LGWR switch)" alert* | awk '{print $1, $2, $3, $4, $5}'

 

이 명령어는 로그 스위치 이벤트가 발생한 날짜와 시간을 출력합니다.

아래의 명령어를 사용하여 alert log 파일에서 로그 스위치가 발생한 날짜와 시간만 출력할 수 있습니다.


grep -B 1 "(LGWR switch)" alert* | awk '{print $1, $2, $3, $4, $5}' | grep -v "Thread"

이 명령어는 "Thread 1 advanced to log" 부분을 제외하고 로그 스위치 이벤트가 발생한 날짜와 시간만을 출력합니다.

아래의 명령어를 사용하여 "--" 또는 "Current"로 시작하는 줄을 제외하고 로그 스위치가 발생한 날짜와 시간만 출력할 수 있습니다.


grep -B 1 "(LGWR switch)" alert* | awk '{print $1, $2, $3, $4, $5}' | grep -v "Thread" | grep -v "^--" | grep -v "^Current"

이 명령어는 "--"로 시작하는 줄과 "Current"로 시작하는 줄을 제외하고 로그 스위치 이벤트가 발생한 날짜와 시간만을 출력합니다.

 

위의 결과를 출력하는 쉘 스크립트를 작성합니다.

 

vi a.sh

alert_log_path=/u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log

grep -B 1 "(LGWR switch)" alert* | awk '{print $1, $2, $3, $4, $5}' | grep -v "Thread" | grep -v "^--" | grep -v "^Current"

 

 

 

<리눅스의 쉘 스크립트를 파이썬에서 호출하기>

import paramiko   # SSH 접속을 위한 라이브러리를 임폴트 합니다. 

# 리눅스 서버 정보
hostname = '192.168.56.103'    # 서버의 접속 가능한 IP 주소
username = 'oracle'            # 접속할 유져명
password = 'oracle'            # 접속할 유져의 패스워드

# bash 스크립트의 경로
script_path = "/home/oracle/a.sh"  # 실행할 bash 스크립트의 경로입니다.

# SSH 클라이언트 객체 생성
ssh = paramiko.SSHClient()  # ssh 클라이언트 객체를 생성합니다.
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
# host key policy 를 자동으로  추가하도록 설정합니다.

# 리눅스 서버에 접속
ssh.connect(hostname, username=username, password=password)

# bash 스크립트를 실행하고 그 결과를 저장합니다.
stdin, stdout, stderr = ssh.exec_command(f'sh {script_path}')


# 결과를 출력합니다.
print(stdout.read().decode('utf-8'))

# 접속 종료
ssh.close()

 

<리스트를 담는 코드>

import paramiko   # SSH 접속을 위한 라이브러리를 임폴트 합니다. 

# 리눅스 서버 정보
hostname = '192.168.56.104'    # 서버의 접속 가능한 IP 주소
username = 'oracle'            # 접속할 유져명
password = 'oracle'            # 접속할 유져의 패스워드

# bash 스크립트의 경로
script_path = "/home/oracle/a.sh"  # 실행할 bash 스크립트의 경로입니다.

# SSH 클라이언트 객체 생성
ssh = paramiko.SSHClient()  # ssh 클라이언트 객체를 생성합니다.
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
# host key policy 를 자동으로  추가하도록 설정합니다.

# 리눅스 서버에 접속
ssh.connect(hostname, username=username, password=password)

# bash 스크립트를 실행하고 그 결과를 저장합니다.
stdin, stdout, stderr = ssh.exec_command(f'sh {script_path}')

# 결과를 바이트에서 문자열로 디코드
output = stdout.read().decode('utf-8')

# 줄바꿈 문자를 기준으로 문자열을 분할하여 리스트로 변환
output_list = output.split('\n')  #split로 구분

# 마지막 요소가 빈 문자열일 경우 제거
if output_list[-1] == '':
    output_list.pop()

# 리스트 출력 #빈문자가 아닐경우에 출력
print(output_list)

 


<위의 리스트를 판다스 데이터 프레임으로 생성>

import paramiko   # SSH 접속을 위한 라이브러리를 임폴트 합니다. 

# 리눅스 서버 정보
hostname = '192.168.56.104'    # 서버의 접속 가능한 IP 주소
username = 'oracle'            # 접속할 유져명
password = 'oracle'            # 접속할 유져의 패스워드

# bash 스크립트의 경로
script_path = "/home/oracle/a.sh"  # 실행할 bash 스크립트의 경로입니다.

# SSH 클라이언트 객체 생성
ssh = paramiko.SSHClient()  # ssh 클라이언트 객체를 생성합니다.
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
# host key policy 를 자동으로  추가하도록 설정합니다.

# 리눅스 서버에 접속
ssh.connect(hostname, username=username, password=password)

# bash 스크립트를 실행하고 그 결과를 저장합니다.
stdin, stdout, stderr = ssh.exec_command(f'sh {script_path}')

# 결과를 바이트에서 문자열로 디코드
output = stdout.read().decode('utf-8')

# 줄바꿈 문자를 기준으로 문자열을 분할하여 리스트로 변환
output_list = output.split('\n')

# 마지막 요소가 빈 문자열일 경우 제거
if output_list[-1] == '':
    output_list.pop()

import  pandas  as  pd

df = pd.DataFrame( output_list, columns=['col1'])
df

 

 

 


판다스 데이터 프레임의 결과에서 시간과 시간사이의 간격시간을 출력하세요
그래서 로그 스위치가 몇분 간격으로 발생했는지 출력하세요

df['col1'] = pd.to_datetime(df['col1'])  # 문자형을 날짜형으로 변환합니다.
df['time_diff'] = df['col1'].diff()  # time_diff 라는 컬럼을 추가하는데 
print(df)

 

위의 코드를 재사용 가능하도록 하나의 코드로 다 모으세요

import paramiko   # SSH 접속을 위한 라이브러리를 임폴트 합니다. 

# 리눅스 서버 정보
hostname = '192.168.56.104'    # 서버의 접속 가능한 IP 주소
username = 'oracle'            # 접속할 유져명
password = 'oracle'            # 접속할 유져의 패스워드

# bash 스크립트의 경로
script_path = "/home/oracle/a.sh"  # 실행할 bash 스크립트의 경로입니다.

# SSH 클라이언트 객체 생성
ssh = paramiko.SSHClient()  # ssh 클라이언트 객체를 생성합니다.
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
# host key policy 를 자동으로  추가하도록 설정합니다.

# 리눅스 서버에 접속
ssh.connect(hostname, username=username, password=password)

# bash 스크립트를 실행하고 그 결과를 저장합니다.
stdin, stdout, stderr = ssh.exec_command(f'sh {script_path}')

# 결과를 바이트에서 문자열로 디코드
output = stdout.read().decode('utf-8')

# 줄바꿈 문자를 기준으로 문자열을 분할하여 리스트로 변환
output_list = output.split('\n')

# 마지막 요소가 빈 문자열일 경우 제거
if output_list[-1] == '':
    output_list.pop()

import  pandas  as  pd

df = pd.DataFrame( output_list, columns=['col1'])
df['col1'] = pd.to_datetime(df['col1'])  # 문자형을 날짜형으로 변환합니다.
df['time_diff'] = df['col1'].diff()  # time_diff 라는 컬럼을 추가하는데 
print(df)

 

위의 결과보고서를 작성할때 너무 빈번하게 로그스위치가 일어나면 지금 DB에 활발하게 insert 작업 또는 update작업이 발생하고 있다는 것.

로그스위치가 빈번하게 발생하는데 성능이 느리다고 보고되면 로그 파일의 갯수와 크기를 늘려야한다. 라고 보고하면 된다

 

 

 

문제1. DBA작업을 편하게 하는 파이썬 자동화 스크립트의 기본 골격 코드를 작성하세요

while   True:
    print( """ ===  dba 작업을 편하게 수행하기 위한 스크립트 총모음 ====

                0.   프로그램을 종료하려면 0번을 누르세요.
                1.  alert log file에서 로그 스위치의 주기를 확인하려면 1번을 누르세요
                2.  현재 테이블 스페이스의 사용량을 시각화 해서 보려면 2번을 누르세요 

        """)

    num =  int( input('원하는 번호를 입력하세요 ~' )  )
    if num == 0:
        break

 

 

 

문제2. 1번alert log file에서 로그 스위치의 주기를 확인하는 스크립트를 추가하세요

while   True:
    print( """ ===  dba 작업을 편하게 수행하기 위한 스크립트 총모음 ====

                0.   프로그램을 종료하려면 0번을 누르세요.
                1.   alert log file 을 분석해서 로그 스위치 주기 확인
                2.   테이블 스페이스 사용량 시각화 하기

        """)

    num =  int( input('원하는 번호를 입력하세요 ~' )  )
    if num == 0:
        break
    elif num ==1:
        import paramiko   # SSH 접속을 위한 라이브러리를 임폴트 합니다. 

        # 리눅스 서버 정보
        hostname = '192.168.56.104'    # 서버의 접속 가능한 IP 주소
        username = 'oracle'            # 접속할 유져명
        password = 'oracle'            # 접속할 유져의 패스워드
        
        # bash 스크립트의 경로
        script_path = "/home/oracle/a.sh"  # 실행할 bash 스크립트의 경로입니다.
        
        # SSH 클라이언트 객체 생성
        ssh = paramiko.SSHClient()  # ssh 클라이언트 객체를 생성합니다.
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
        # host key policy 를 자동으로  추가하도록 설정합니다.
        
        # 리눅스 서버에 접속
        ssh.connect(hostname, username=username, password=password)
        
        # bash 스크립트를 실행하고 그 결과를 저장합니다.
        stdin, stdout, stderr = ssh.exec_command(f'sh {script_path}')
        
        # 결과를 바이트에서 문자열로 디코드
        output = stdout.read().decode('utf-8')
        
        # 줄바꿈 문자를 기준으로 문자열을 분할하여 리스트로 변환
        output_list = output.split('\n')
        
        # 마지막 요소가 빈 문자열일 경우 제거
        if output_list[-1] == '':
            output_list.pop()
        
        import  pandas  as  pd
        
        df = pd.DataFrame( output_list, columns=['col1'])
        df['col1'] = pd.to_datetime(df['col1'])  # 문자형을 날짜형으로 변환합니다.
        df['time_diff'] = df['col1'].diff()  # time_diff 라는 컬럼을 추가하는데 
        print(df)
        break

 

 

while   True:
    print( """ ===  dba 작업을 편하게 수행하기 위한 스크립트 총모음 ====

                0.   프로그램을 종료하려면 0번을 누르세요.
                1.   alert log file 을 분석해서 로그 스위치 주기 확인
                2.   alert log file에서 가장 많이 나오는 에러번호와 그 건수 확인

        """)

    num =  int( input('원하는 번호를 입력하세요 ~' )  )
    if num == 0:
        break
        
    elif num ==1:
        import paramiko   # SSH 접속을 위한 라이브러리를 임폴트 합니다. 

        # 리눅스 서버 정보
        hostname = '192.168.56.104'    # 서버의 접속 가능한 IP 주소
        username = 'oracle'            # 접속할 유져명
        password = 'oracle'            # 접속할 유져의 패스워드
        
        # bash 스크립트의 경로
        script_path = "/home/oracle/a.sh"  # 실행할 bash 스크립트의 경로입니다.
        
        # SSH 클라이언트 객체 생성
        ssh = paramiko.SSHClient()  # ssh 클라이언트 객체를 생성합니다.
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
        # host key policy 를 자동으로  추가하도록 설정합니다.
        
        # 리눅스 서버에 접속
        ssh.connect(hostname, username=username, password=password)
        
        # bash 스크립트를 실행하고 그 결과를 저장합니다.
        stdin, stdout, stderr = ssh.exec_command(f'sh {script_path}')
        
        # 결과를 바이트에서 문자열로 디코드
        output = stdout.read().decode('utf-8')
        
        # 줄바꿈 문자를 기준으로 문자열을 분할하여 리스트로 변환
        output_list = output.split('\n')
        
        # 마지막 요소가 빈 문자열일 경우 제거
        if output_list[-1] == '':
            output_list.pop()
        
        import  pandas  as  pd
        
        df = pd.DataFrame( output_list, columns=['col1'])
        df['col1'] = pd.to_datetime(df['col1'])  # 문자형을 날짜형으로 변환합니다.
        df['time_diff'] = df['col1'].diff()  # time_diff 라는 컬럼을 추가하는데 
        print(df)
        break
    elif num == 2:
        file = open('C:\\test\\alert_orcl.log', 'r')
        text = file.read()
    
        text2 = text.split() # 문자열을 어절별로 분리해서 text2 리스트를 구성
        k = [ ]
        for  i  in   text2:  # 리스트의 요소를 하나씩 불러오는데
            if 'ora-'  in  i.lower():  # 요소를 소문자로 변환하고 그 요소가 ora- 를 포함하면
                k.append(i)   # k 리스트의 요소로 i 에 들어있는 값을 추가합니다.
    
        import  pandas  as  pd
    
        df= pd.DataFrame( k, columns=['col1'] )  # k 리스트를 가지고 df 라는 판다스 데이터
        df                                      # 프레임을 생성하는데 컬럼을 col1 으로 지정
    
        from pandasql import sqldf
        pysqldf = lambda q : sqldf(q,globals() )
        q = """select col1, count(*)
                from df
                group by col1
                order by 2 desc;"""
    
        print(pysqldf(q))