본문 바로가기

Infra/DB

[AWS RDS] mysql: table doesn't exist

1. 문제상황

Spring 백단에서 프로퍼티별 개발환경을 나누고 로컬에선 H2db, 개발서버에선 aws rds mysql 8.0 을 사용하도록 datasource를 연결하였다.
그리고 h2db쪽에서는 쿼리가 잘 날라가는 걸 확인.
테스트 완료후 ec2에 배포하고 개발서버에서 실행했는데 table이 없다고 나옴.

 

 

2. 시도한 방법들

- JPA Naming Strategy

기본적으로 아무런 설정을 하지 않으면 @Table 의 지정한 name 이 대 소문자를 구분하여 쿼리가 날라간다. 즉 , mysql 에서는 테이블 명이 USERS 였고 JPA entity 의 name 은 users 였기 때문에 테이블을 찾지 못하는것.

그래서 별도의 namingStrategy를 프로퍼티에서 지정해주거나 엔티티에서 Table name을 지정할 때 대문자로하면 된다.. 
그러나 DB tool 내에서의 쿼리콘솔에서도 대소문자 구분하고 싶지 않은데 ... 일단 근본적인 해결방법은 아닌 것 같다.

 

- lower_case_table_names

mysql 에서 테이블이름에 대해 대 소문자를 구분하는지에 대한 설정을 할 수 있다.
mysql 이 설치된 경로로 들어가 my.cnf 에서 lower_case_table_names = 1 로 설정하면 되지만 AWS RDS에서는 할 수 없기 때문에 RDS 파라미터 설정에서 바꿔줘야한다.

 

 

0 -> 1 로 변경.

뭣 ..

파라미터 그룹이 연결되어있어서 변경이 안된다니깐 default 로 다시 바꾸고 파라미터 수정 재시도.

뭣..

 

찾아보니 mysql 8.0 부터는 DB를 최초 생성했을 때만 설정할 수 있다고 나온다.. 
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.KnownIssuesAndLimitations.html#MySQL.Concepts.ParameterNotes

 

Known issues and limitations for Amazon RDS for MySQL - Amazon Relational Database Service

Some existing DB instances have a lower limit. For example, MySQL DB instances created before April 2014 have a file and table size limit of 2 TB. This 2 TB file size limit also applies to DB instances or read replicas created from DB snapshots taken befor

docs.aws.amazon.com

 

3. 결론

결론적으로 내가 손 댈수 있는건 네이밍 전략밖에 없었다.
application.yml 의 physical-strategy를 CustomNamingStrategy 를 PhysicalNamingStrategy 인터페이스를 구현받아 사용하여 해결하였다. 

package com.greenroom.server.api.utils;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class JpaCustomPhysicalNamingStrategy implements PhysicalNamingStrategy {

    @Override
    public Identifier toPhysicalCatalogName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
        if(identifier == null){
            return null;
        }
        return convertToSnakeCase(identifier);
    }

    @Override
    public Identifier toPhysicalColumnName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
        if(identifier == null){
            return null;
        }
        return convertToSnakeCase(identifier);
    }

    @Override
    public Identifier toPhysicalSchemaName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
        if(identifier == null){
            return null;
        }
        return convertToSnakeCase(identifier);
    }

    @Override
    public Identifier toPhysicalSequenceName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
        if(identifier == null){
            return null;
        }
        return convertToSnakeCase(identifier);
    }

    @Override
    public Identifier toPhysicalTableName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
        if(identifier == null){
            return null;
        }
        return convertToSnakeCaseAndUpperCase(identifier);
    }

    private Identifier convertToSnakeCase(final Identifier identifier) {
        final String regex = "([a-z])([A-Z])";
        final String replacement = "$1_$2";
        final String newName = identifier.getText()
                .replaceAll(regex, replacement)
                .toLowerCase();
        return Identifier.toIdentifier(newName);
    }

    private Identifier convertToSnakeCaseAndUpperCase(final Identifier identifier) {
        final String regex = "([a-z])([A-Z])";
        final String replacement = "$1_$2";
        final String newName = identifier.getText()
                .replaceAll(regex, replacement)
                .toUpperCase();
        return Identifier.toIdentifier(newName);
    }
}

 

 

적용해보면 from 절의 테이블 지정이 대문자로 바뀌어있는 것을 볼 수 있다.

Recent Posts
Popular Posts
Archives
Visits
Today
Yesterday