운영되고 있던 시스템의 Database는 MySQL 5.7용 AWS RDS 서비스를 이용중이었다.
곧 MySQL 5.7용 AWS RDS의 표준 지원이 종료된다는 메일을 받기도 했고...
5.7은 현재로써 구버전이라 MySQL 8.0 버전으로 업그레이드를 하기로 하였다.
AWS RDS는 DB 인스턴스 수정을 통해 DB 엔진 버전 변경이 가능하여 아래 사진과 같이 버전 업그레이드를 진행하였다.
?characterEncoding=UTF-8&connectionCollation=utf8mb4_general_ci
변경 전 (MySQL 5.7)
변경 후 (MySQL 8.0)
character_set
utf8
-> utf8mb4
utf8(utf8mb3)
은 MySQL 8.0에서 더 이상 지원되지 않아 utf8mb4
로 변경해줘야한다.collation
utf8mb3_general_ci
-> utf8mb4_general_ci
utf8mb4_unicode_ci
방식이utf8mb4_general_ci
보다 더 복잡한 알고리즘을 사용하여 더 나은 정확도나 다국어 지원에 좋다.
복잡한 알고리즘때문에 속도 차이가 있지만 요새 하드웨어 성능이 많이 올라 큰 차이가 없다.
1(구분 안함)
-> 0(구분 함, default value)
utf8
-> utf8mb4
utf8_general_ci
-> utf8mb4_general_ci
-- 변경
ALTER DATABASE (DB NAME)
CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 확인
SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA;
utf8
-> utf8mb4
utf8_general_ci
-> utf8mb4_general_ci
-- table, column 모두 변경
ALTER TABLE (table_name)
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 확인
SHOW TABLE STATUS FROM (table_name);
기존에 사용중인 프로시저나 함수의 DDL을 살펴보면 입출력값의 Character나 Collate가 utf8
로 되어있다면 utf8mb4
로 변경해주어야 함.
utf8
-> utf8mb4
utf8_general_ci
-> utf8mb4_general_ci
아래와 같이 old_password()
function을 생성하여 사용 예정
DELIMITER //
CREATE DEFINER=`db_name`@`%` FUNCTION `db_name`.`old_password`(pwd TEXT) RETURNS varchar(41) CHARSET utf8mb4
NO SQL
COMMENT 'password() 함수는 MySQL8.0에서 deprecated 되었음.'
BEGIN
DECLARE result VARCHAR(41);
SET result = CONCAT('*', UPPER(SHA1(UNHEX(SHA1(pwd)))));
RETURN result;
END;
DELIMITER ;
utf8mb4_general_ci
로 설정되어 있음.?characterEncoding=UTF-8&connectionCollation=utf8mb4_general_ci
MySQL5.7에서는 정상적으로 작동하지만 8.0버전에서는 문법 오류 발생
SELECT *
FROM table
GROUP BY column DESC
-- 아래와 같이 ORDER BY절 필요
SELECT *
FROM table t
GROUP BY t.column
ORDER BY t.column DESC
expr1
의 타입과 expr2
타입이 일치해야함-- t.date는 date타입, ''는 text타입으로 불일치
SELECT NULLIF(t.date, '') FROM table t
-- IFNULL(), CONCAT()는 타입이 일치하지 않아도 문법 오류가 발생하지 않음
SELECT IFNULL(t1.date. '') FROM table t1;
SELECT CONCAT(t2.date. 'text') FROM table t2;
-- 확인 쿼리
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME IS NOT NULL
AND CHAR_LENGTH(CONSTRAINT_NAME) >= 64;
MySQL 5.x에서 사용되던 인덱스가 있다면 MySQL 8.0로 업그레이드 후 성능 테스트를 수행해야 한다.
옵티마이저가 변경되었기 때문에 같은 쿼리라도 실행계획이 달라질 수 있다.
MySQL 5.x에서는 성능 향상에 도움이 됐지만 MySQL 8.x에서는 오히려 성능 저하를 유발할 수도 있다.
MySQL 8.x에서는 파티션의 각 테이블스페이스를 공용 테이블스페이스에 저장할 수 없다. 그래서 파티션의 테이블스페이스가 공용 테이블스페이스에 저장된 것이 있는지 먼저 확인하고, 있다면 ALTER TABLE ... REORGANIZE
명령을 실행해 개별 테이블스페이스를 사용하도록 변경해야 한다.
아래 쿼리로 공용 테이블스페이스에 저장된 게 없는 것으로 확인.
SELECT table_name, partition_name, subpartition_name, tablespace_name
FROM information_schema.partitions
WHERE table_schema = 'your_database_name'
AND tablespace_name = 'innodb_system';
참고
https://dev.mysql.com/blog-archive/inplace-upgrade-from-mysql-5-7-to-mysql-8-0/
https://dev.mysql.com/blog-archive/upgrading-to-mysql-8-0-here-is-what-you-need-to-know/
https://dev.mysql.com/blog-archive/new-defaults-in-mysql-8-0/