메인 콘텐츠로 건너뛰기

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
MySQL에서 utf8이라는 이름의 문자 집합은 UTF-8이 아닙니다. 이모지 이전 시대에 멈춘, 문자당 3바이트의 부분 집합(utf8mb3)이며, 이모지, 많은 CJK 표의 문자, 수학 기호 같은 4바이트 문자는 모두 거기에 저장되지 않습니다. utf8mb4가 진짜 UTF-8입니다. MySQL 8.0 이상에서는 새 테이블의 기본값이지만, 더 오래된 버전에서 만들었거나 DDL에 utf8을 명시한 테이블은 여전히 이 함정을 안고 있습니다.

실패

\xF0\x9F\x9A\x80은 로켓 이모지의 4바이트입니다. 엄격한 SQL 모드가 꺼져 있으면 이것은 대신 경고로 도착하고, 문제의 문자는 조용히 ?로 바뀌며 문자열의 나머지는 유지됩니다. 이쪽이 더 나쁩니다: 몇 주 뒤에 데이터를 보고 알게 됩니다.

변환할 것 찾기

어떤 테이블과 열이 아직 3바이트 utf8을 쓰는지 메타데이터에 물어보세요:
스키마와 테이블의 기본값도 확인하세요. 그렇지 않으면 새 열이 잘못된 상태로 태어납니다:

변환

CONVERT TO CHARACTER SET은 테이블을 다시 쓰면서 열 정의와 저장된 데이터를 모두 변환합니다:
그다음 앞으로 만들 객체가 올바른 문자 집합을 물려받도록 기본값을 고치세요:
큰 테이블에서 이것은 전체 다시 쓰기입니다. 다른 차단형 ALTER와 같이 취급하고 평소의 온라인 마이그레이션 도구로 실행하세요. 스키마 마이그레이션을 보세요. 변환 전에 확인할 2가지:
  • 인덱스 길이. VARCHAR(255) 고유 인덱스는 utf8mb3에서 765바이트가 필요했지만 utf8mb4에서는 1,020바이트가 필요합니다. 최신 InnoDB 기본값(DYNAMIC 행 형식)은 3,072바이트를 허용하므로, 이 문제는 주로 아주 오래된 서버에서 REDUNDANT나 COMPACT 행 형식으로 넘어온 테이블에서 생깁니다. ALTER가 최대 키 길이 오류로 실패하면, 먼저 테이블의 행 형식을 확인하세요.
  • 연결 문자 집합. 저장은 경로의 절반일 뿐입니다. 클라이언트 연결이 utf8mb3으로 협상하면, 열이 담을 수 있더라도 이모지는 전송 중에 죽습니다. 세션이 실제로 무엇을 쓰는지 확인하세요:
character_set_client와 character_set_connection이 둘 다 utf8mb4로 읽혀야 합니다. 대부분의 최신 드라이버는 기본적으로 그렇게 하지만, 오래된 JDBC와 PHP 구성은 utf8을 고정할 수 있습니다.

콜레이션, 간단히

문자 집합은 바이트가 무엇을 뜻하는지이고, 콜레이션은 바이트를 어떻게 비교하는지입니다. MySQL 8.x의 utf8mb4에서는 utf8mb4_0900_ai_ci가 기본값이자 일반적으로 올바른 답입니다: 악센트를 구분하지 않고, 대소문자를 구분하지 않으며, 올바른 유니코드 9.0 순서입니다. 문자열 열로 조인되는 테이블 사이에 콜레이션을 섞으면 변환이 강제되고 인덱스를 건너뛸 수 있으므로, 하나를 골라 어디서나 사용하세요. 문자 집합과 콜레이션이 비교 규칙을 깊이 다룹니다.

함께 보기