1. 개요
새로운 서비스를 개발하면서 DevOps와 함께 새로운 인프라를 세팅하면서 MySQL의 Default character set에 대한 이슈가 발생하였습니다. 이번에 경험한 이슈는 default character set 이슈로, 에러 코드는 1366 Incoreect string value 이슈입니다. 해당 이슈를 처리하는 방법 중 가장 쉬운 방법은 drop database를 수행 후 새로 database를 생성 후 migrate 하는 것이 가장 빠르고 쉬운 방법입니다. 새로운 서비스를 개발하는 데 있어서 아직 런칭 이전이기 때문에 보다 쉬운 방법을 택하는 방법도 좋겠지만, database를 초기화 할 수 없는 상태에 이슈를 해결할 수 있는 방법이 어떻게 해야할지 문득 궁금해졌습니다. 때문에 번거롭지만, database를 날리지 않고 방법을 찾아보았습니다.
Environment
# requirements.txt
# ...
django==4.1.2
# via
# -r requirements.in
# django-axes
# django-celery-beat
# django-filter
# django-model-utils
# django-storages
# djangorestframework
# djangorestframework-simplejwt
# drf-yasg
djangorestframework==3.14.0
# via
# -r requirements.in
# djangorestframework-simplejwt
# drf-yasg
mysqlclient==2.1.1
# via -r requirements.in
# etc...
Python
복사
새로운 서비스를 개발하면서 레거시 프로젝트에서 경험하지 못했던 이슈를 경험하고자 위와 같이 requirements.txt를 구성하였습니다.
2. Trouble shooting
문제가 되는 부분은 다음과 같은 에러 상태입니다.
OperationalError라고 출력되며 트러블 슈팅 해결을 위해 (1366, “Incorrect string value: [SOME_UNICODE])라고 검색이 가능합니다. 검색하여 구한 다른 해결 책은 매우 다양했습니다.
•
Database default character set 수정
◦
drop database → create database ‘db_name’ → python3 manage.py migrate
•
Modify table character set and collation
•
Modify column character set and collation
대부분은 Default character set을 수정하여 database를 새로 만들어 migrate하거나 아니면 테이블 혹은 컬럼의 character set을 수정하면 된다고 하였습니다. 다만 이런 방법으로 해결하고자 할 때 한 가지 추가적인 이슈가 있었습니다.
object_repr
필요한 필드를 모두 수정하더라도 따로 설정하지 않았던 column에 대해 character set 이슈가 계속 발생했습니다. Model에 설정하였던 필드와 별개로 object_repr 라는 필드에서 incorect string value 에러가 발생하였습니다.
이 필드의 위치는 django_admin_log 테이블에서 varchar 로 설정된 컬럼이 있습니다. 해당 필드 또한 데이터가 함께 쌓이는 구조이기 때문에 한글이나 Unicode가 들어가게 되면 위와 같이 에러가 계속 발생하게 됩니다.
id | int(11) | NO | PRI | FIELD5 | auto_increment |
action_time | datetime(6) | NO | |||
object_id | longtext | YES | |||
object_repr | varchar(200) | NO | |||
action_flag | smallint(5) unsigned | NO | |||
change_message | longtext | NO | |||
content_type_id | int(11) | YES | MUL | ||
user_id | char(32) | NO | MUL |
3. Solve
ALTER DATABASE `DB_NAME` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';
SET character_set_server = "utf8mb4";
SET collation_connection = "utf8mb4_general_ci";
SET foreign_key_checks=0; # if foregin key is exists.
alter table django_admin_log CONVERT TO CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';
alter table MODEL_TABLE1 CONVERT TO CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';
alter table MODEL_TABLE2 CONVERT TO CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';
SET foreign_key_checks=1; # if foregin key is exists.
alter table MODEL_TABLE1 modify column MODEL_COLUMN1 longtext character set utf8mb4 collate utf8mb4_general_ci;
alter table MODEL_TABLE1 modify column MODEL_COLUMN2 longtext character set utf8mb4 collate utf8mb4_general_ci;
alter table MODEL_TABLE2 modify column MODEL_COLUMN1 varchar(50) character set utf8mb4 collate utf8mb4_general_ci;
alter table django_admin_log modify column object_repr varchar(200) character set utf8mb4 collate utf8mb4_general_ci;
SQL
복사