https://repost.aws/knowledge-center/aurora-mysql-stop-cluster-seven-days

 

Stop Amazon Aurora cluster for longer than seven days

I want to stop an Amazon Relational Database Service (Amazon Aurora clusters) for longer than the seven-day duration.

repost.aws

 

  • Aurora 특성상 7 Days 이후에는 자동으로 시작
  • Lambda - EventBridge(스케쥴) 로 AutoStop 생성
    • AWS SNS 서비스로 Event 수신
  • Chatops 
    • Slackbot 으로 방식으로 Aurora 현재 상태 확인및 테스트 이후 Stop & Start 구현
import json
import os
import time
from urllib import request, parse
import boto3

def lambda_handler(event, context):
    try:
        bot_token = os.environ.get('BOT_TOKEN')
        if not bot_token:
            raise ValueError("BOT_TOKEN environment variable is not set")
        
        body = json.loads(event['body'])
        print(f"Received body: {body}")
        
        if 'challenge' in body:
            return {
                'statusCode': 200,
                'body': json.dumps({'challenge': body['challenge']})
            }
            
        if 'event' in body:
            if 'token' in body and body['token'] != os.environ.get('VERIFICATION_TOKEN'):
                return {
                    'statusCode': 403,
                    'body': json.dumps({'error': 'Invalid verification token'})
                }
                
            slack_event = body['event']
            if (slack_event['type'] == 'message' and 
                'channel_type' in slack_event and 
                slack_event['channel_type'] == 'channel' and
                'text' in slack_event):
                
                text = slack_event.get('text', '').strip()
                print(f"text: {text}")
                
                if text.startswith("stop "):
                    cluster_name = text.split("stop ")[1].strip()
                    initial_response = stop_specific_rds_cluster(cluster_name)
                    
                    # 초기 응답 전송
                    post_message_to_slack(initial_response, slack_event['channel'], bot_token)
                    
                    # 중지가 성공적으로 시작된 경우에만 상태 확인
                    if "Stopping cluster" in initial_response:
                        # 상태 확인 및 결과 전송
                        status_response = wait_for_cluster_stop(cluster_name)
                        post_message_to_slack(status_response, slack_event['channel'], bot_token)
        
        return {
            'statusCode': 200,
            'body': json.dumps({'message': 'Success'})
        }
        
    except Exception as e:
        print(f"Error in lambda_handler: {str(e)}")
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

def wait_for_cluster_stop(cluster_name, max_attempts=30, delay_seconds=10):
    """
    RDS 클러스터가 완전히 중지될 때까지 대기하고 상태를 확인합니다.
    
    Args:
        cluster_name (str): RDS 클러스터 식별자
        max_attempts (int): 최대 확인 시도 횟수
        delay_seconds (int): 각 확인 사이의 대기 시간(초)
    
    Returns:
        str: 상태 확인 결과 메시지
    """
    rds_client = boto3.client('rds')
    attempt = 0
    
    try:
        while attempt < max_attempts:
            cluster = rds_client.describe_db_clusters(
                DBClusterIdentifier=cluster_name
            )['DBClusters'][0]
            
            current_status = cluster['Status']
            
            if current_status == 'stopped':
                return f"✅ Cluster {cluster_name} has been successfully stopped."
            elif current_status == 'stopping':
                if attempt == 0:
                    return f"⏳ Cluster {cluster_name} is stopping. Status will be updated..."
                time.sleep(delay_seconds)
                attempt += 1
            else:
                return f"❌ Unexpected cluster status: {current_status}. Please check manually."
        
        return f"⚠️ Timeout waiting for cluster {cluster_name} to stop. Current status: {current_status}"
        
    except rds_client.exceptions.DBClusterNotFoundFault:
        return f"❌ Error: Cluster {cluster_name} not found during status check."
    except Exception as e:
        error_msg = f"❌ Error checking cluster status: {str(e)}"
        print(error_msg)
        return error_msg

def post_message_to_slack(response_text, channel_id, bot_token):
    try:
        url = "https://slack.com/api/chat.postMessage"
        headers = {
            'Authorization': f"Bearer {bot_token}",
            'Content-Type': 'application/json'
        }
        payload = json.dumps({
            'channel': channel_id,
            'text': response_text
        }).encode('utf-8')
        
        req = request.Request(url, data=payload, headers=headers)
        response = request.urlopen(req)
        response_data = json.loads(response.read().decode())
        
        if not response_data.get('ok'):
            print(f"Slack API error: {response_data.get('error')}")
            
    except Exception as e:
        print(f"Error posting message to Slack: {str(e)}")

def stop_specific_rds_cluster(cluster_name, rds_client=None):
    if rds_client is None:
        rds_client = boto3.client('rds')
        
    try:
        cluster = rds_client.describe_db_clusters(
            DBClusterIdentifier=cluster_name
        )['DBClusters'][0]
        
        if cluster['Status'] != 'available':
            return f"❌ Cluster {cluster_name} is not in available state (current: {cluster['Status']})."
            
        tags = rds_client.list_tags_for_resource(
            ResourceName=cluster['DBClusterArn']
        )['TagList']
        
        if not any(tag['Key'] == 'autostop' and tag['Value'] == 'yes' 
                  for tag in tags):
            return f"❌ Cluster {cluster_name} does not have required autostop tag."
            
        rds_client.stop_db_cluster(DBClusterIdentifier=cluster_name)
        return f"⏳ Stopping cluster: {cluster_name}..."
        
    except rds_client.exceptions.DBClusterNotFoundFault:
        return f"❌ Cluster {cluster_name} not found."
    except Exception as e:
        error_msg = f"❌ Error stopping cluster {cluster_name}: {str(e)}"
        print(error_msg)
        return error_msg

mysql version  8.4 LTS

  • 8.4 변동사항 많아서 보류
  • 8.0.4 로 uprade
https://dev.mysql.com/blog-archive/introducing-mysql-innovation-and-long-term-support-lts-versions/

 

한대의 인스턴스 Minor Upgrade 순서

- MySQL 셧다운 → 엔진파일 덮어쓰기(변경) → MySQL 서버(mysqld) 시작 → MySQL upgrade 실행
- 업그레이드 시 mysqld vs mysql_upgrade
실제 업그레이드는 두가지 단계로 나뉘어서 처리 ( 1단계: mysqld, 2단계 : mysql_upgrade)

 

순서

 

  • mysql 8,0.4 download & 압축해제ll
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.40-linux-glibc2.28-x86_64.tar.xz
sudo su
tar -xvf mysql-8.0.40-linux-glibc2.28-x86_64.tar.xz -C /usr/local​
  • 심볼릭 링크  해재 후 재설정
cd /usr/local
unlink mysql
ln -s mysql-8.0.40-linux-glibc2.28-x86_64 mysql​

 

  • mysql 중지
/usr/local/mysql/bin/mysqladmin -u root -p shutdown
  • upgrade 수행
/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &


업그레이드 프로그램 
8.0.16 미만 : mysql_upgrade
8.0.16 이상 : mysqld

로그 확인
2024-12-10T10:50:44.469133-00:00 4 [System] [MY-013381] [Server] Server upgrade from '80023' to '80200' started.
2024-12-10T10:50:51.334428-00:00 4 [System] [MY-013381] [Server] Server upgrade from '80023' to '80200' completed.
  • my.cnf 변경
expire_logs_days=7
-> binlog_expire_logs_seconds=604800
  • mysqlcheck
 /usr/local/mysql/bin/mysqlcheck -u root -p --all-databases --check-upgrade​
  • version 확인
SELECT @@version​

'MySQL (Aurora) > Troubleshooting' 카테고리의 다른 글

메모리 Resize 장애 (MHA)  (3) 2024.09.25
Mysql 5.7 Online DDL varchar column size변경  (1) 2024.09.03
  • key_lenght 가 실제 인덱스 길이보다 짧다면 인덱스 정상적으로 안타는것
  • 실행계획 확인시 key_lenght도  말고 filterd 조건을 자세히 봐야한다
    • filterd  조건이 높을수록 인덱스를 정상적으로 탐색
    • filterd  낮을수록 남은 row가 많다는 뜻 인덱스를 정상적으로 안탐

 

filerd가 1이므로 나머지 99% 남았다는뜻 - 인덱스 확인 필요

'MySQL (Aurora) > DB Tuning' 카테고리의 다른 글

인덱스 힌트  (0) 2024.10.07
형 변환 튜닝  (2) 2024.10.02
  • Jmeter로 성능테스트해보자
  • Jmeter 장점 : sysbench와 다르게 쿼리를 설정할수있음

 

2. JMeter 설치하기

1) java 설치 : jmeter를 사용하려면 자바 8 버전이상이 필요하다. 아래 링크에서 OS맞는 버전을 다운로드 받아 설치한다. (있는 경우 설치할 필요X)

https://www.oracle.com/java/technologies/javase-downloads.html

 

2) jmeter 설치 : 아래 링크에서 jmeter툴을 설치할 수 있다. 바이너리 파일 중 zip파일을 다운로드 받는다. 

https://jmeter.apache.org/download_jmeter.cgi

3) JMeter툴 실행 : 압축을 풀고 bin 폴더 안에 있는 jmeter.bat 열어 JMeter을 실행시킨다. cmd창으로 로그 등을 확인할 수 있으므로 툴이 뜨고난 후에도 cmd창은 닫지 않는다.

 

3. JMeter - DB관련 도구 설치

1) 접속드라이버 설치 : Jmeter가 DB에 접속하기 위해서는 접속드라이버가 필요하다. 아래 링크에 들어가 platform independent 메뉴에서 zip파일을 다운로드 받으면 된다. 

https://dev.mysql.com/downloads/connector/j/

다운로드 받은 파일 압축을 푼다. .jar로 끝나는 JDBC 드라이버 파일을 복사해 jmeter폴더의 lib폴더에 넣어준다.

 

4. JMeter 사용하기 (미리 구성된 템플릿 이용)

Jmeter는 시작할 때 lib폴더를 참조하므로, Jmeter를 닫고 재실행한다.

 

1) 템플릿 생성 : [ File > Templates ]를 클릭하고 상단 셀렉트박스에서 JDBC Load Test를 클릭한다. create 버튼을 눌러 생성한다.

 

2) Connector 설정 : 테스트 서버에 접속정보를 입력

각 옵션에 대한 설명 확인 ▷ [ https://jmeter.apache.org/usermanual/component_reference.html ]

따로 완료 버튼은 없다. 

 

3) Thread Group 설정 : 쓰레드 그룹은 부하를 줄 양과 빈도를 설정

위와 같이 설정하면 10유저가 30초 안에 모두 실행해야 되므로, (30/10)초에 한 번씩 10개가 DB에 연결된다. 그리고 이 작업을 2번 반복한다. 

 

4) JDBC Request 설정 : 실제 테스트할 로직을 작성

 

5) Summary Report 추가 : summary report는 요청성공여부 통계를 내준다. DB에 부하가 많이 걸려서 요청에 실패하게 될 경우, 대략 몇 건까지 요청이 성공했는지 파악할 수 있다.

 

6) 결과 확인 : [ 파일 > 저장 ]을 눌러 파일을 저장하고 JDBC Request화면을 띄우고 상단에 초록색으로 된 시작버튼을 눌러 시작한다.

좋아요3
공유하기
게시글 관리
구독하기

'MySQL (Aurora) > TECH' 카테고리의 다른 글

Mysql Gap Lock  (1) 2024.10.16
mysql 8.0 error_log filter  (0) 2024.10.04
Aurora(Mysql) Version 별 Connector / Driver 설정  (1) 2024.09.13

1. Mysql Gap Lock 이란?

인덱스 레코드 사이에 잠금

Isolation_level이 Repeatable Read일떄만 발생

 

단점 : 인덱스 사이에 Gap Lock이 발생해서 데드락 유발

 

 

Gap Lock : https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-gap-locks

 

cf)

https://medium.com/daangn/mysql-gap-lock-%EB%8B%A4%EC%8B%9C%EB%B3%B4%EA%B8%B0-7f47ea3f68bc

'MySQL (Aurora) > TECH' 카테고리의 다른 글

Mysql 성능테스트(jmeter)  (0) 2024.10.16
mysql 8.0 error_log filter  (0) 2024.10.04
Aurora(Mysql) Version 별 Connector / Driver 설정  (1) 2024.09.13
  • 원인

      분포도에 따라 실행계획이 변하는 현상 발생

     user 의 개수가 단일이 아닌 복수개의 경우 reg_date 기준으로 실행계획 생성

  • 쿼리
select
        ifnull(acb.score, 0)
from
        tb_abc_log abc
where
        abc.user = #user
        and user.reg_date > DATE_SUB(NOW(), INTERVAL 1 DAY)
order by
        user.reg_date desc
 limit 1
  • 해결방법
    • 인덱스 힌트로 실행계획 고정

                    USE_INDEX(ix_abc_log_user)

select
        ifnull(acb.score, 0)
from
        tb_abc_log abc USE_INDEX(ix_abc_log_user)
where
        abc.user = #user
        and user.reg_date > DATE_SUB(NOW(), INTERVAL 1 DAY)
order by
        user.reg_date desc
 limit 1

'MySQL (Aurora) > DB Tuning' 카테고리의 다른 글

mysql 실행계획 시 유의점  (0) 2024.12.03
형 변환 튜닝  (2) 2024.10.02
  • 기능
    • mysql 8.0 이상 error_log filter 기능 추가 (문자열)

  https://dev.mysql.com/doc/refman/8.4/en/error-log-priority-based-filtering.html

  • log_error_suppression_list
    • error log 수집 시 해당 문자열 제외 수집 
[Warning] [MY-013360] [Server] Plugin sha256_password reported: ''sha256_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'
[Warning] [MY-013360] [Server] Plugin mysql_native_password reported: ''mysql_native_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead' (sql_authentication.cc:4314)

 

원인

mysql 8.0의 기본 인증 플러그인은 예전의 mysql_native_password가 아니라 caching_sha2_password이므로 해당 에레머세지가 발생
방법: 보안연결이나 RSA 연결로 인증 필요 다만 클라이언트 에서 컨트롤 필요하므로 에러 수정불가

 

  • 설정방법
    • 설치형 mysql
1) 파라미터
[mysqld]
log_error_verbosity=2     # error and warning messages only
log_error_suppression_list='ER_PARSER_TRACE,MY-010001,10002'
mysql> select @@log_error_suppression_list;
+------------------------------+
| @@log_error_suppression_list |
+------------------------------+
|                              |
+------------------------------+
1 row in set (0.00 sec)

2) 동적
mysql> set global log_error_suppression_list='MY-013360';
Query OK, 0 rows affected (0.01 sec)
mysql> select @@log_error_suppression_list;
+------------------------------+
| @@log_error_suppression_list |
+------------------------------+
| MY-013360                 |
+------------------------------+
  • Aurora

파라미터 변경

 

'MySQL (Aurora) > TECH' 카테고리의 다른 글

Mysql 성능테스트(jmeter)  (0) 2024.10.16
Mysql Gap Lock  (1) 2024.10.16
Aurora(Mysql) Version 별 Connector / Driver 설정  (1) 2024.09.13
  • 원인
    • mysql varchar와 int 조인시 형이 안맞아서 인덱스를 안타는 현상
  • 해결

1) 근본적인 해결

  표준화를 통한 테이블의 형 맞춤

2) 단기적인 해결

 인덱스를 타기위한 형변환을 통한 튜닝

 

  • 현상

  tb_apple 의 order_id(VARCHAR) 와 tb_pay 의 id(INT) 칼럼이 형이 틀려서 인덱스를 안타는 현상

  • 해결

SELECT * FROM 

FROM tb_voice voice
INNER JOIN tb_pay result ON voice.tid = result .id

LEFT JOIN adb.tb_apple apple ON apple.order_id = result.id

 

-> 

SELECT * FROM 

FROM tb_voice voice
INNER JOIN tb_pay result ON voice.tid = result .id

LEFT JOIN adb.tb_abc apple ON apple.order_id = CONVERT(result_info.id, CHAR)

'MySQL (Aurora) > DB Tuning' 카테고리의 다른 글

mysql 실행계획 시 유의점  (0) 2024.12.03
인덱스 힌트  (0) 2024.10.07

MHA 구성으로 메모리 Resize 작업(재부팅 필요) 으로 장애 발생

  • 작업 시나리오

       0) MHA 세팅 확인

       1) Standby 메모리 Resize

       2) Online Failover 

       3) 구 Master 메모리 Resize

      

  • 장애 포인트

        Online Failover 이후 API가 VIP로 접속 안되는 현상 발생

  • 기존 Case

        기존에 Driver 버전 이슈라던지 다른 이슈일경우에는 API 세션이 있었는데 이 경우에는 세션이 한개도 안보임

        처음 발생한 Case

  • 원인 파악

        네트워크 작업으로 인한 방화벽이 막힌걸로 의심  ( 세션이 한개도없음)

  •  해결

        allowed_rule 이 빠진걸로 확인

        

 

'MySQL (Aurora) > Troubleshooting' 카테고리의 다른 글

mysql minor version upgrade  (0) 2024.12.12
Mysql 5.7 Online DDL varchar column size변경  (1) 2024.09.03

 

  • Connector  vs Driver
정의 데이터베이스와 통신을 위한 전체 라이브러리 (JDBC 드라이버) 데이터베이스에 연결을 생성하고 관리하는 특정 클래스
역할 드라이버 클래스를 포함한 모든 데이터베이스 통신 기능 제공 JDBC를 통해 연결을 설정하고, 쿼리 실행을 관리함
예시 MySQL Connector/J
(mysql-connector-java-x.x.x.jar)
com.mysql.cj.jdbc.Driver
(MySQL 드라이버 클래스)
포함관계 커넥터는 드라이버 클래스와 그 외 다양한 기능을 포함 드라이버 클래스는 커넥터의 구성 요소 중 하나
설명 드라이버 클래스뿐만 아니라 JDBC 연결에 필요한 모든 기능을 포함한 라이브러리 패키지 커넥터 라이브러리 안에 포함된 데이터베이스 연결을 위한 특정 클래스
결론 Connector(패키지) 안에 Driver(클래스) 에 같은 DBMS로 설정 필요
  • JDBC

  •    
  • MySQL Connector/JMariaDB Connector/JAWS JDBC Driver
  MySQL Connector/J MariaDB Connector/J AWS JDBC Driver
호환성 MySQL 및 Aurora 가능 MySQL 및 Aurora 가능 Aurora만 가능
서비스 일반적인 지원중단 Aurora만 최적화 
안정성 가장 안정적 지원중단 Aurora만 최적화
  •  결론 : MySQL Connector/J  사용 권장

 

  • MySQL(Aurora) Version  Recommand Connector / Driver
    Aurora Version MySQL Version Connector Driver
    v2 5.7 MySQL Connector/J 5.14 com.mysql.jdbc.Driver
    v3 8.0 MySQL Connector/J 8.0 com.mysql.cj.jdbc.Driver
    • MySQL Connector/J 5.1.44 has been released'에 따르면 MySQL Connector/J 5.1.18보다 새로운 버전인 MySQL Connector/J 5.1.44는 MySQL 5.5, 5.6, 5.7용 드라이버로 설명되어 있으며

                 에서 MySQL 8.0.23 이상으로 연결하기 위해서는 MySQL Connector/J 8.0으로 업그레이드하는 것이 좋다는 설명을 확인할 수 있습니다.

 

 

 

 

'MySQL (Aurora) > TECH' 카테고리의 다른 글

Mysql 성능테스트(jmeter)  (0) 2024.10.16
Mysql Gap Lock  (1) 2024.10.16
mysql 8.0 error_log filter  (0) 2024.10.04

+ Recent posts