AWS RDS MySQL 마이그레이션 체크 사항

AWS Aurora RDS MySQL에서 AWS MySQL 8.0으로 마이그레이션을 진행 후, save 메소드를 사용하는 api를 호출할 때, TypeORM에서 id 값 관련된 쿼리 error가 발생하였다. 

TypeORMError: Cannot update entity because entity id is not set in the entity.

해당 에러가 발생하는 부분의 쿼리를 로깅해보면 정상적으로 쿼리가 생성되지만, 타겟 entity의 id가 entity에 세팅되지 않았다는 에러는 발생되므로 ORM이 아닌 DB가 이슈일 가능성이 있었다. 

INSERT INTO "tableName"("id", "createdAt", "updatedAt", "body") 
VALUES (DEFAULT, DEFAULT, DEFAULT, ?) ["example body"]

 

AWS RDS에 ssh 터널링을 통해 접근해서 id 값이 없다는 이슈가 발생하는 테이블의 information schema에서 table 속성의 AUTO_INCREMENT값을 select해왔다.

SELECT AUTO_INCREMENT 
FROM information_schema.tables 
WHERE table_name = '테이블 명' AND table_schema = DATABASE();

 

기존 다른 MySQL 테이블들은 위처럼 다음 id 값이 뜬다.

 

정상적인 information_schema를 가진 테이블이라면, 위처럼 AUTO_INCREMENT 값이 있어야하는데 이슈가 발생한 테이블의 AUTO_INCREMENT 값이 null로 지정되어있었다.

 

TypeORM의 @PrimaryGeneratedColumn 데코레이터를 id 칼럼에 지정해서 정상적이라면 id에 AUTO_INCREMENT가 걸려있어야했다. 이슈가 발생했던 원인은 AUTO_INCREMENT가 null 이다보니 추가되는 데이터의 id 칼럼 값이 자동으로 지정되지않아 결과적으로 DB에서 저장 에러가 발생했던 것이다.

 

AUTO_INCREMENT가 null이 된 원인은 AWS Aurora RDS Serverless에서 AWS RDS MySQL로 마이그레이션을 진행하면서 테이블과 데이터만 마이그레이션이 진행되고, information_schema 설정 값들은 마이그레이션되지 않아 MySQL 기본 설정값으로 설정되어 있었다. 그러다 보니 테이블은 정상적으로 마이그레이션이 되었는데 id 칼럼의 설정에 AUTO_INCREMENT가 안 걸려있게 된 것이다.

 

해당 이슈를 해결하려  MAX(id) + 1의 값으로 AUTO_INCREMENT 설정 값을 변경하려 했지만, 권한 에러가 발생하였다. 

ERROR 1227 (42000) at line 374: Access denied; 
you need (at least one of) the SUPER privilege(s) for this operation

 

해당 권한 에러는 RDS DB 인스턴스에 존재하지 않는 DEFINER 속성 사용자로 객체를 생성하려고 시도했거나 사용자가 필요한 SUPER 사용자 권한을 가지고 있지 않은 속성 사용자를 생성하려고 시도할 때 발생한다고 AWS 공식 문서에 적혀있었다.

 

Amazon RDS for MySQL 또는 MariaDB의 mysqldump 오류 해결

MySQL 또는 MariaDB를 실행하는 Amazon RDS(Amazon Relational Database Service) DB 인스턴스를 사용 중입니다. mysqldump를 사용하여 데이터를 가져오거나 내보낼 때 오류가 발생했습니다. 이 오류를 해결하려면 어

aws.amazon.com

 

해당 권한 이슈를 해결? 우회?하기 위해 DB를 덤프 뜬 다음 생성된 dump.sql 파일의 DEFINER 속성을 삭제한 후 직접 AUTO_INCREMENT 속성을 각 테이블의 id 값마다 추가해주는 방법을 사용하였다. 

 

DEFINER 속성을 삭제하기 위해 sed 명령어를 사용하여 dump.sql 내부에 있는 DEFINER=와 관련된 내용을 모두 삭제하였다.

sed 's/\sDEFINER=`[^`]*`@`[^`]*`//g' -i dump.sql

 

이후 vim (또는 vscode)로 해당 파일을 열어서 직접 테이블마다 id 값에 AUTO_INCREMENT 속성이 붙어있는지 확인하고, 없다면 추가해주었다.

 

DROP TABLE IF EXISTS `테이블 명`;

CREATE TABLE `테이블 명` (
  `id` int NOT NULL,
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `body` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

 

위처럼 id 에 int NOT NULL 만 붙어있고, AUTO_INCREMENT 속성이 누락되어있는 것을 확인할 수 있다. 누락되어있는 AUTO_INCREMENT를 모든 테이블의 id 칼럼마다 추가해주면 된다.

 

DROP TABLE IF EXISTS `테이블 명`;

CREATE TABLE `테이블 명` (
  `id` int NOT NULL AUTO_INCREMENT,
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `body` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

 

수정한 dump.sql 파일을 덤프 떳던 DB에 접속해서 Run SQL을 통해 실행시키면 기존 테이블이 드랍된 이후 정상적으로 AUTO_INCREMENT 값이  Max(id) + 1의 값으로 설정되어있는 것을 확인할 수 있었다. AWS RDS에서 마이그레이션을 진행할 때는 누락된 테이블 설정 값이 있는지 확인해야한다.

'개발 > MySQL' 카테고리의 다른 글

[MySQL] RANK() 로 구현하는 순위 계산  (0) 2023.06.27