# 1071-지정된 키가 너무 깁니다. 최대 키 길이는 767 바이트입니다.


562

다음 명령을 실행할 때 :

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

이 오류 메시지가 나타납니다.

#1071 - Specified key was too long; max key length is 767 bytes

column1 및 column2에 대한 정보 :

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

varchar(20)21 바이트 varchar(500)만 필요하고 501 바이트 만 필요 하다고 생각 합니다. 따라서 총 바이트 수는 522보다 적으며 767보다 작습니다. 왜 오류 메시지가 표시됩니까?

#1071 - Specified key was too long; max key length is 767 bytes

5
520 바이트가 아니라 2080 바이트로 767 바이트를 훨씬 초과하므로 column1 varchar (20) 및 column2 varchar (170)을 수행 할 수 있습니다. 문자 / 바이트 equiv를 원한다면 latin1
Rahly

3
나는 당신의 계산이 약간 잘못되었다고 생각합니다. mysql은 1 또는 2 개의 여분 바이트를 사용하여 값 길이를 기록합니다. 열의 최대 길이가 255 바이트 이하인 경우 1 바이트, 255 바이트보다 긴 경우 2입니다. VARCHAR는 (20) 61 바이트 VARCHAR를 사용하도록 utf8_general_ci 인코딩 문자 당 3 바이트를 필요로 (500)는 총 1,502 1,563 바이트의 바이트 사용
lackovic10

3
mysql> information_schema.character_sets에서 maxlen, character_set_name을 선택하십시오. 여기서 character_set_name in ( 'latin1', 'utf8', 'utf8mb4'); 맥 슬렌 | character_set_name ------ | ------------------- 1 | latin1 ------ | ------------------- 3 | utf8 ------ | ------------------- 4 | utf8mb4
lackovic10

15
'문자 / 바이트 equiv를 원하면 latin1을 사용하십시오 . ' 이 작업을 수행하지 마십시오 . Latin1 정말, 정말 짜증나. 후회하게 될 것입니다.
Stijn de Witt

해결책은 stackoverflow.com/a/52778785/2137210 을 참조하십시오
Pratik

답변:


490

767 바이트는 MySQL 버전 5.6 (및 이전 버전)에서 InnoDB 테이블에 대해 명시된 접두사 제한 입니다. MyISAM 테이블의 길이는 1,000 바이트입니다. MySQL 버전 5.7 이상에서는이 제한이 3072 바이트로 증가했습니다.

또한 utf8mb4로 인코딩 된 큰 char 또는 varchar 필드에 인덱스를 설정하면 767 바이트 (또는 3072 바이트)의 최대 인덱스 접두사 길이를 4로 나누어 191이되어야합니다. utf8mb4 문자의 최대 길이는 4 바이트입니다. utf8 문자의 경우 최대 바이트 접두사 길이는 254가되는 3 바이트입니다.

한 가지 옵션은 VARCHAR 필드에 하한을 두는 것입니다.

이 문제에 대한 응답 에 따른 다른 옵션 은 전체 금액이 아닌 열의 하위 집합을 얻는 것입니다.

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

키를 적용 할 필요가 있으면 조정하지만,이 엔터티와 관련된 데이터 모델을 검토하여 MySQL 제한에 맞지 않고 의도 한 비즈니스 규칙을 구현할 수있는 개선 사항이 있는지 알아볼 가치가 있는지 궁금합니다.


4
전체 금액이 아닌 열의 하위 집합을 지정하여 적용합니다. 좋은 해결책입니다.
Steven

204
길이 제한보다 훨씬 낮은 필드가 길이 제한을 초과하는 이유는 설명하지 않습니다.
Cerin

6
@Cerin이 위의 누락 정보에서 편집을 시도했지만 다른 사람들도 누락 된 것으로 분명히 간주되지만 의견으로 더 적합하다고 거부됩니다. 500 + 20> 767을 이해하려는 사람들은 Julien의 답변에 대한 Stefan Endrullis의 의견을 참조하십시오.
Letharion

8
문제가 될 수 있습니다. 예를 들어 : 필드 이름 (255)이 있고 utf8mb4를 사용하는 것처럼 name (191)에서이 필드에 고유 한 것을 추가합니다. 내 사용자에게 'IJUE3ump5fiUuCi16jSofYS234MLschW4wsIktKiBrTPOTKBK6Vteh5pNuz1tKjy ... aO500mlJs'로 이름을 추가하고 다른 사용자는이 'IJUE3ump5fiUuCi16jSofYS234MLschW4wTKKKBKTKTKPKTKTKPKTKTKTKPKTKPKTKPKTKTKTKTKTKTZK4K'BKPKZBJKJBKJB ... 중복 항목에 멈춰 있지 않은 유효성 검사를 통과해야합니다.
vee

28
색인 한계는 문자가 아닌 767 바이트 입니다. 그리고 Mysql의 utf8mb4문자 세트 (세계의 나머지 부분은 utf8이라고 함) 는 문자 당 최대 4 바이트가 필요 하기 때문에 최대 색인 만 가능합니다 VARCHAR(191). MySQL을의 utf8당신이 그것을 사용하는 만약 그렇다면 (세계의 나머지가 깨진 호출) 문자 세트는 문자 당 최대 3 바이트가 필요합니다 (이 당신이 해야하지 ) 할 수 있습니다에 대한 인덱스까지VARCHAR(255)
스테인 드 위트

403

INNODB / Utf-8에 문제가 발생 UNIQUE하여 VARCHAR(256)필드에 색인 을 넣으려고하면로 전환하십시오 VARCHAR(255). 255가 한계 인 것 같습니다.


246
허용되는 문자 수는 문자 집합에 따라 다릅니다. UTF8은 문자 당 최대 3 바이트, utf8mb4 최대 4 바이트 및 latin1 만 1 바이트를 사용할 수 있습니다. 따라서 utf8의 경우 키 길이는 255 자로 제한됩니다 3*255 = 765 < 767.
Stefan Endrullis

9
이로 인해 많은 좌절을 겪었습니다. 감사합니다. 사용자가 767b 제한에 도달했다고 주장하여 InnoDB를 사용한다는 점을 고려하면 허용되는 답변 IMO 여야합니다.
TheCarver

8
Stefan Endrullis가 말했듯이 문자 세트에 따라 다릅니다. 3 바이트를 사용하는 UTF8을 사용하는 경우 : 255x3 = 765는 767 한계보다 낮고 256x3 = 768은 더 높습니다. 그러나 UTF8mb4를 사용하면 255 * 4 = 1020이므로 실제 해결책은 아닙니다.
bernhardh

25
이 대답은 맞습니다. 그러나 255가 실제로 작동하면 utf8불행히도 Mysql을 사용하고 있음을 의미합니다 . 기본 다국어 평면의 문자 만 인코딩 할 수 있습니다. 캐릭터가 해당 범위를 벗어나는 문제가 발생합니다. 예를 들어 그들이 추가 한 이모 지 문자는 그 밖의 것으로 생각합니다. 그래서 대신 전환 VARCHAR(255)에 스위치, VARCHAR(191) 로 인코딩 전환 utf8mb4(실제로는 단지 UTF8이지만, MySQL은.의 compat를 다시 유지하고 싶어).
Stijn de Witt

1
여러 열의 고유 제약 조건에는 도움이되지 않습니다. 또한 OP의 다중 열 고유 제약 조건에서는 작동하지 않습니다. (전체 크기는 825 바이트입니다)
Barett

351

당신이 한계에 도달했을 때. 다음을 설정하십시오.

  • 이노 DB utf8 VARCHAR(255)
  • 이노 DB utf8mb4 VARCHAR(191)

34
이것이 가장 좋은 대답입니다. 간단하고 요점까지 똑 바르고 utf8mb4한계 도 포함 합니다 (이모 지 등을 허용하므로 최신 데이터베이스에 가장 많이 사용되는 인코딩입니다).
Claudio Holanda

10
767/4 ~ = 191이고
767/3

11
어디서 어떻게 설정합니까?
Dinesh Sunny

1
예, 진술 ENGINE=InnoDB DEFAULT CHARSET=utf8의 끝에 지정 CREATE TABLE하면 VARCHAR(255)기본 키 를 가질 수있었습니다 . 감사.
xonya

1
누군가가 그에게 +1 한도 191을 초과하도록
주었습니다

147

MySQL은 문자열에서 문자 당 바이트 수에 대해 최악의 경우를 가정합니다. MySQL 'utf8'인코딩의 경우 문자 당 3 바이트입니다. 해당 인코딩은을 (를) 초과하는 문자를 허용하지 않기 때문입니다 U+FFFF. MySQL 'utf8mb4'인코딩의 경우, 문자 당 4 바이트입니다. 이는 MySQL이 실제 UTF-8을 호출하기 때문입니다.

따라서 'utf8'을 사용한다고 가정하면 첫 번째 열에는 60 바이트의 인덱스가 있고 두 번째 열에는 1500 바이트가 필요합니다.


4
— 아마도 이것은 utf8mb4를 사용할 때 191 * 4 = 764 <767로 (최대) 191로 설정해야한다는 것을 의미합니다.
Isaac

2
@Isaac 그렇습니다.
morganwahl

2
나는 이것이 정답이라고 생각하지만 그러한 문제를 해결하기 위해 무엇을 해야하는지 자세히 설명 할 수 있습니까? 적어도 나와 같은 MySQL 멍청한 놈에게는?
Adam Grant

이 색인 한계를 극복하는 방법은 없습니다. 여기서의 질문은 독특한 제약에 관한 것입니다. 이를 위해 길이가 무제한 인 텍스트 열 하나와 해당 텍스트의 해시 (예 : MD5)를 저장하고 고유 제한 조건에 해시 열을 사용할 수 있습니다. 텍스트를 변경할 때 프로그램이 해시를 최신 상태로 유지해야하지만 너무 많은 문제없이 처리 할 수있는 다양한 방법이 있습니다. 솔직히 MySQL은 그런 일 자체를 구현해야하므로 그렇게 할 필요는 없습니다. MariaDB에 내장 기능이 있다고해도 놀라지 않을 것입니다.
morganwahl 2016 년

매우 긴 varchar 열의 고유 인덱스는 거의 없습니다. 디자인 문제 일 수 있으므로 왜 필요한지 생각해보십시오. 검색을 위해 색인을 원한다면 191 자 이내의 '키워드'필드를 고려하거나 텍스트를 간단한 설명과 길고 완전한 텍스트 등으로 분할하십시오. 또는 전체 텍스트 검색이 필요한 경우 전문 소프트웨어를 사용하는 것이 좋습니다 Apache Lucene과 같은
Stijn de Witt

56

이 쿼리를 쿼리 전에 실행하십시오.

SET @@global.innodb_large_prefix = 1;

이로 제한이 증가합니다 3072 bytes.


4
innodb_large_prefix를 전역으로 변경하면 단점이 있습니까? 그리고 그 DB는 "전세계"입니까 아니면 모든 DB가 TOTALLY GLOBAL입니까?
SciPhi

5
비표준 행 형식을 사용하는 경우에만 적용됩니다. dev.mysql.com/doc/refman/5.5/en/…를 참조하십시오 . 특히, DYNAMIC 및 COMPRESSED 행 형식을 사용하는 InnoDB 테이블의 경우 인덱스 키 접두어를 767 바이트 (최대 3072 바이트)보다 길게하려면이 옵션을 활성화하십시오. 기본 행 형식은 영향을받지 않습니다.
Chris Lear

5
이것은 나를 위해 잘 작동했습니다-자세한 내용과 가이드는 here에서 찾을 수 있습니다 : mechanics.flite.com/blog/2014/07/29/…
cwd

1
이 후에 mysql 서버를 다시 시작해야합니까?
SimpleGuy

7
이 답변에서 중요한 부분이 누락되었습니다. innodb_file_format수 있어야합니다 BARRACUDA및 테이블 수준에서 당신은 사용해야 ROW_FORMAT=DYNAMIC하거나 ROW_FORMAT=COMPRESSED. 가이드와 함께 위의 @cwd의 의견을 참조하십시오.
q0rban

46

라 라벨 프레임 워크 솔루션

당으로 Laravel 5.4 * 문서. ; 다음과 같이 파일 의 boot메소드 내에서 기본 문자열 길이를 설정해야 app/Providers/AppServiceProvider.php합니다.

use Illuminate\Support\Facades\Schema;

public function boot() 
{
    Schema::defaultStringLength(191); 
}

이 수정에 대한 설명은 Laravel 5.4. * 설명서에서 제공합니다 .

라 라벨은 utf8mb4기본적으로 문자 세트를 사용하는데 , 여기에는 데이터베이스에 "이모 지"를 저장하는 기능이 포함됩니다. 5.7.7 릴리스 이전의 MySQL 버전 또는 10.2.2 릴리스 이전의 MariaDB를 실행중인 경우, MySQL이 인덱스를 작성하기 위해 마이그레이션에서 생성 된 기본 문자열 길이를 수동으로 구성해야 할 수도 있습니다. 에서 Schema::defaultStringLength메소드 를 호출하여이를 구성 할 수 있습니다 AppServiceProvider.

또는 innodb_large_prefix데이터베이스에 대한 옵션을 활성화 할 수 있습니다. 이 옵션을 올바르게 활성화하는 방법에 대한 지침은 데이터베이스 설명서를 참조하십시오.


10
@BojanPetkovic 잘 Laravel 문제에서 왔으며이 답변은 실제로 내 문제를 해결했습니다.
mkmnstr

이 답변은 훌륭합니다. 그러나 왜 이것이 정확히 작동하는지 아는 사람이 있습니까?
UeliDeSchwert

1
@Bobby Laravel 문서는 "Index Lengths & MySQL / MariaDB"제목에 설명되어 있습니다. laravel.com/docs/5.4/migrations#creating-indexes
Ali Shaukat

1
@Bobby 답변을 업데이트했습니다. 이 수정 프로그램에 대한 laravel 설명서에서 제공하는 설명을 추가했습니다.
Ali Shaukat

39

어떤 문자 인코딩을 사용하고 있습니까? UTF-16과 같은 일부 문자 집합은 문자 당 하나 이상의 바이트를 사용합니다.


8
UTF8 인 경우 문자는 최대 4 바이트를 사용할 수 있으므로 20 자 열은 20 * 4 + 1바이트이고 500 자 열은 500 * 4 + 2바이트입니다.
Thanatos

5
그것이 가치있는 것에 대해, 나는 똑같은 문제가 있었고 utf8_general_ci에서 utf8_unicode_ci로 전환하면 문제가 해결되었습니다. 나는 왜 그런지 모르겠다 :(
Andresch Serj

11
인덱스가 있는 VARCHAR(256)열의 경우 UNIQUE데이터 정렬을 변경해도 @Andresch와 마찬가지로 영향을 미치지 않았습니다. 그러나 길이를 256에서 255로 줄이면 문제가 해결되었습니다. 문자 당 767 / 최대 4 바이트가 최대 191을 생성하는 이유를 이해하지 못합니까?
Arjan

10
255*3 = 765; 256*3 = 768. 서버가 문자 당 3 바이트를 가정하는 것으로 보입니다. @Arjan
Amber

21
@Greg : 정확하지만 정교해야합니다. UTF-8 자체는 코드 포인트 당 1-4 바이트를 사용합니다. MySQL의 "문자 세트"(실제 인코딩)에는 UTF-8의 일부 를 인코딩 할 수 있고 코드 포인트 당 1–3 바이트를 사용하며 BMP 외부의 코드 포인트를 인코딩 할 수없는 "utf8"이라는 문자 세트 가 있습니다. 또한 "utf8mb4"라는 다른 문자 세트도 포함되는데,이 코드 세트는 코드 포인트 당 1-4 바이트를 사용하며 모든 유니 코드 코드 포인트를 인코딩 할 수 있습니다. (utf8mb4는 UTF-8이고, utf8은 이상한 UTF-8 버전입니다.)
Thanatos

28

varchar (20)에는 21 바이트 만 필요하지만 varchar (500)에는 501 바이트 만 필요하다고 생각합니다. 따라서 총 바이트 수는 522보다 적으며 767보다 작습니다. 왜 오류 메시지가 표시됩니까?

UTF8은 문자열을 저장하기 위해 문자 당 3 바이트를 필요로 하므로 허용되는 767 바이트를 초과 하는 20 + 500 자 = 20 * 3 + 500 * 3 = 1560 바이트입니다 .

UTF8의 제한은 767/3 = 255 자 이며, 문자 당 4 바이트를 사용하는 UTF8mb4의 경우 767/4 = 191 자입니다.


제한보다 긴 열을 사용해야하는 경우이 문제에 대한 두 가지 솔루션이 있습니다.

  1. "저렴한"인코딩을 사용하십시오 (문자 당 더 적은 바이트가 필요합니다)
    내 경우에는 SEO 문자열을 포함하는 열에 고유 색인을 추가해야했습니다. SEO에는 [A-z0-9\-]문자 만 사용하기 때문에 문자 latin1_general_ci당 하나의 바이트 만 사용했습니다. 따라서 열의 길이는 767 바이트입니다.
  2. 열에서 해시를 만들고 그에 대해서만 고유 인덱스를 사용하십시오.
    나에게 다른 옵션은 SEO의 해시를 저장할 다른 열을 만드는 것이 었습니다.이 열에는 UNIQUESEO 값이 고유해야합니다. 또한 KEY검색 속도를 높이기 위해 원래 SEO 열에 색인을 추가 합니다.

이 트릭을했다. varchar (256)이 있고 varchar (250)로 변경해야했습니다.
MaRmAR

25

오류 메시지가 표시되는 이유에 대한 답변은 이미 많은 사용자가 이미 답변했습니다. 내 대답은 그대로 수정하고 사용하는 방법에 관한 것입니다.

이 링크 에서 참조하십시오 .

  1. MySQL 클라이언트 (또는 MariaDB 클라이언트)를 엽니 다. 명령 줄 도구입니다.
  2. 암호를 묻고 올바른 암호를 입력하십시오.
  3. 이 명령을 사용하여 데이터베이스를 선택하십시오 use my_database_name;

데이터베이스가 변경됨

  1. set global innodb_large_prefix=on;

쿼리 OK, 영향을받는 0 개의 행 (0.00 초)

  1. set global innodb_file_format=Barracuda;

쿼리 OK, 영향을받는 0 개의 행 (0.02 초)

  1. 쉬운 관리를 위해 phpMyAdmin 또는 이와 유사한 데이터베이스로 이동하십시오. > 데이터베이스 선택> 테이블 구조 보기 > 작업 탭으로 이동 하십시오. > ROW_FORMATDYNAMIC으로 변경 하고 변경 사항을 저장하십시오.
  2. 테이블 구조 탭으로 이동 > 고유 버튼을 클릭하십시오 .
  3. 끝난. 이제 오류가 없어야합니다.

이 수정의 문제점은 db를 다른 서버 (예 : localhost에서 실제 호스트로)로 내보내고 해당 서버에서 MySQL 명령 행을 사용할 수없는 경우입니다. 거기서 작동하게 할 수 없습니다.


위의 쿼리를 입력 한 후에도 여전히 오류가 발생하면 "phpmyadmin"으로 이동하여 "collation"을 원하는대로 설정하십시오 (나를 위해 "utf8_general_ci"를 사용함)> 적용을 클릭하십시오 (이미 utf8 인 경우에도)
Anthony Kal

귀하의 지침에 맞는 도구를 사용하고 있지는 않지만 사람들이 실제로 문제를 해결 하도록 돕기 위해 여전히 투표 하고 있습니다. 문제의 원인에 대한 끝없는 설명이 있지만 실제로 문제를 해결하는 방법에 대해서는 거의 설명이 없습니다.
Teekin

20
Specified key was too long; max key length is 767 bytes

latin-1문자 세트 를 사용하는 경우에만 1 바이트가 1 문자이므로 메시지가 표시 됩니다. 을 사용하면 utf8키 열을 정의 할 때 각 문자가 3 바이트로 간주됩니다. 을 사용하면 utf8mb4키 열을 정의 할 때 각 문자가 4 바이트 인 것으로 간주됩니다. 따라서 키 필드의 문자 제한에 1, 3 또는 4를 곱하면 (예 : 키 필드에서 허용하려는 바이트 수) 결정해야합니다. uft8mb4를 사용하는 경우 기본 InnoDB 기본 키 필드에 대해 191 자만 정의 할 수 있습니다. 767 바이트를 위반하지 마십시오.


16

긴 열의 md5 열을 추가 할 수 있습니다


이렇게하면 이러한 열에 대한 범위 스캔을 수행 할 수 없습니다. VARCHAR의 접두사 길이를 사용하면이 특성을 유지하면서 인덱스에서 잘못된 일치를 유발할 수 있습니다 (스캔 및 행 조회를 통해 제거) (허용 된 답변 참조). (이것은 기본적으로 수동으로 구현 된 해시 인덱스이며, 슬프게도 MysQL은 InnoDB 테이블을 지원하지 않습니다.)
Thanatos

테스트 목적으로 H2와의 호환성을 유지해야했고 해시 열을 사용하는 것이 잘 작동했기 때문에 접두사 인덱스를 사용할 수 없었습니다. 나는 것이 강하게 같은 충돌을 만드는 악의적 인 사용자를 방지하기 위해 대신 MD5의 SHA1으로 충돌 방지 기능을 사용하는 것이 좋습니다. 쿼리 중 하나가 전체 열 값이 아닌 해시 값만 검사하는 경우 인덱스 충돌을 이용하여 데이터를 유출 할 수 있습니다.
리틀 마이크

16

교체 utf8mb4utf8가져 오기 파일입니다.

여기에 이미지 설명을 입력하십시오


왜 정확히 그렇게해야합니까? 또한, 이것이 단점이 있다면 (내가 가정 한) 이것을 언급해야합니다
Nico Haase

13

utf8mb4를 사용하여 VARCHAR (255) 필드에 UNIQUE 인덱스를 추가하려고 할 때이 문제가 발생했습니다. 문제가 이미 여기에 잘 설명되어 있지만, 우리가 이것을 이해하고 해결하는 방법에 대한 실용적인 조언을 추가하고 싶었습니다.

utf8mb4를 사용할 때 문자는 4 바이트로 계산되지만 utf8에서는 3 바이트로 계산됩니다. InnoDB 데이터베이스에는 인덱스에 767 바이트 만 포함될 수있는 제한이 있습니다. 따라서 utf8을 사용할 때는 255자를 저장할 수 있지만 (767/3 = 255), utf8mb4를 사용하면 191자를 저장할 수 있습니다 (767/4 = 191).

VARCHAR(255)utf8mb4를 사용하여 필드에 대한 일반 색인을 절대적으로 추가 할 수 있지만 다음과 같이 색인 크기가 자동으로 191 자에서 잘립니다 unique_key.

191 자에서 잘린 색인을 보여주는 Sequel Pro 스크린 샷

일반 인덱스는 MySQL이 데이터를 더 빨리 검색하는 데 도움을주기 위해 사용되기 때문에 좋습니다. 전체 필드를 색인 할 필요는 없습니다.

그렇다면 왜 MySQL은 일반 인덱스에 대해 인덱스를 자동으로 자르지 만 고유 인덱스에 대해 시도 할 때 명시적인 오류가 발생합니까? 글쎄, MySQL이 삽입되거나 업데이트되는 값이 이미 존재하는지 알아낼 수 있으려면 실제로 값의 일부가 아닌 전체 값을 인덱싱해야합니다.

하루가 끝날 때 필드에 고유 인덱스를 사용하려면 필드의 전체 내용이 인덱스에 맞아야합니다. utf8mb4의 경우 VARCHAR 필드 길이를 191 자 이하로 줄입니다. 해당 테이블 또는 필드에 utf8mb4가 필요하지 않은 경우 utf8로 다시 드롭하고 255 개의 길이 필드를 유지할 수 있습니다.


11

내 원래 답변은 다음과 같습니다.

데이터베이스를 삭제하고 다음과 같이 다시 작성하면 오류가 사라집니다.

drop database if exists rhodes; create database rhodes default CHARACTER set utf8 default COLLATE utf8_general_ci;

그러나 모든 경우에 작동하지는 않습니다.

실제로 문자 세트 utf8(또는 utf8mb4)가있는 VARCHAR 열에서 특정 길이보다 긴 문자가있는 VARCHAR 열에 인덱스를 사용하면 문제가 발생 합니다. 의 경우utf8mb4 특정 길이는 191입니다.

MySQL 데이터베이스에서 긴 인덱스를 사용하는 방법에 대한 자세한 내용은이 기사의 긴 인덱스 섹션을 참조하십시오. http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database- 문자 세트에서 UTF-8로


openmeetings 설정 문제 해결 (BTW 당신은 ​​내 밤을 저장 :-)
Ludo

11

5 가지 해결 방법 :

한계는 5.7.7 (MariaDB 10.2.2?)에서 증가했습니다. 그리고 5.6 (10.1)에 약간의 작업으로 증가 할 수 있습니다.

CHARACTER SET utf8mb4를 사용하려고 시도하여 한계에 도달 한 경우 그런 다음 오류 중 하나를 피하려면 다음 중 하나를 수행하십시오 (각각 단점이 있음).

  Upgrade to 5.7.7 for 3072 byte limit -- your cloud may not provide this;
  Change 255 to 191 on the VARCHAR -- you lose any values longer than 191 characters (unlikely?);
  ALTER .. CONVERT TO utf8 -- you lose Emoji and some of Chinese;
  Use a "prefix" index -- you lose some of the performance benefits.
  Or... Stay with older version but perform 4 steps to raise the limit to 3072 bytes:

SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_large_prefix=1;
logout & login (to get the global values);
ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- (or COMPRESSED)

-http : //mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes


10

이 문제를 다음과 같이 수정했습니다.

varchar(200) 

로 교체

varchar(191)

200 이상인 모든 varchar는 191로 바꾸거나 텍스트를 설정합니다.


이것이 나에게도 효과가 있었다. varchar (250)가 있었지만 데이터는 그렇게 길지 않았습니다. varchar (100)로 변경했습니다. 아이디어 주셔서 감사합니다 :)
Arun Basil Lal

7

나는이 주제에 대한 검색을 마침내 마침내 약간의 사용자 정의 변경을 얻었다

MySQL 워크 벤치 6.3.7 버전의 경우 그래픽 간 단계 사용 가능

  1. Workbench를 시작하고 연결을 선택하십시오.
  2. 관리 또는 인스턴스로 이동하여 옵션 파일을 선택하십시오.
  3. Workbench가 구성 파일을 읽을 수있는 권한을 요청한 후 확인을 두 번 눌러 허용하십시오.
  4. 중앙 위치에 관리자 옵션 파일 창이 나타납니다.
  5. InnoDB 탭으로 이동하여 innodb_large_prefix가 일반 섹션에서 확인되지 않은 경우 확인하십시오.
  6. innodb_default_row_format 옵션 값을 DYNAMIC으로 설정하십시오.

6.3.7 이하 버전의 경우 직접 옵션을 사용할 수 없으므로 명령 프롬프트로 이동해야합니다.

  1. CMD를 관리자로 시작하십시오.
  2. mysql 서버가 설치된 디렉터로 이동 대부분의 경우 "C : \ Program Files \ MySQL \ MySQL Server 5.7 \ bin"에 있으므로 명령은 "cd \" "cd Program Files \ MySQL \ MySQL Server 5.7 \ bin"입니다.
  3. 이제 mysql -u userName -p databasescheema 명령을 실행하십시오. 이제 각 사용자의 비밀번호를 요청했습니다. 비밀번호를 입력하고 mysql 프롬프트에 입력하십시오.
  4. 일부 전역 설정을 설정해야합니다. set global innodb_large_prefix = on; 전역 설정 innodb_file_format = barracuda; 전역으로 설정 innodb_file_per_table = true;
  5. 이제 마지막으로 필수 테이블의 ROW_FORMAT을 기본적으로 COMPACT로 변경해야합니다.
  6. 다음 명령을 사용하십시오 alter table table_name ROW_FORMAT = DYNAMIC;
  7. 끝난

이것을 찾을 수 없습니다 : 6. innodb_default_row_format 옵션 값을 DYNAMIC으로 설정하십시오.
Adrian Cid Almaguer

내가 사용하는 경우 set global innodb_default_row_format = DYNAMIC;나는이 메시지가 표시 : ERROR 1193 (HY000) : 알 수없는 시스템 변수 'innodb_default_row_format'
아드리안 시드 Almaguer

워크 벤치에서 cmd로 오류가 발생했습니다. 나는 작업대에서 그것을 직접했다.
Abhishek


1
이 변수가 v5.7.9에서 소개되었고 v5.6.33 버전을 사용하는 문제를 확인했습니다.
Adrian Cid Almaguer

7

라 라벨 5.7 ~ 6.0

따라야 할 단계

  1. 이동 App\Providers\AppServiceProvider.php .
  2. 제공자에게 추가 use Illuminate\Support\Facades\Schema; 에게 맨 위에 .
  3. 부팅 기능 내부 추가 Schema::defaultStringLength(191);

그 모든 것을 즐기십시오.


Laravel 5.8에서도 근무했습니다.
Neo

이것은 나쁜 해결책입니다. 이유 : 인덱스는 무한히 길어야합니다. 무언가에 고유 한 색인을 적용 할 때 대부분의 시간에 색인이 고정되기를 원합니다. 그것은 당신이 독창적 인 물건을 만들지 않아야 한다는 것을 의미 email하지만, 이메일을 해시하고 독창적이어야합니다. 원시 문자열 데이터와 달리 해시는 너비가 고정되어 있으며 색인없이 문제없이 고유하게 만들 수 있습니다. 문제를 이해하는 대신 확장 할 수없는 끔찍한 사례가 확산되고 있습니다.
NB

5

데이터 정렬을 변경하십시오. 거의 모든 것을 지원 하는 utf8_general_ci 를 사용할 수 있습니다


"거의"는 이것이 장기적인 해결책이 아니라는 좋은 힌트입니다.
Nico Haase

4

테이블을 만들 때로 변경 utf8mb4하면 utf8문제가 해결되었습니다. 예를 들면 다음 CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;과 같습니다 CREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;.


4

그것을 고치기 위해 이것은 매력처럼 작동합니다.

ALTER DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;

내 문제도 데이터베이스 데이터 정렬임을 확인했습니다. 이에 대한 설명이 없습니다. mysql v5.6.32를 사용하고 DB 데이터 정렬은 utf8mb4_unicode_ci입니다.
mahyard 2016 년

2

아래에 주어진 열을 기준으로 두 개의 가변 문자열 열이 utf8_general_ci데이터 정렬을 사용하고 있습니다 ( utf8문자 세트가 암시 됨).

MySQL에서 utf8문자셋은 각 문자에 최대 3 바이트 를 사용합니다 . 따라서 500 * 3 = 1500 바이트를 할당해야하며 이는 MySQL이 허용하는 767 바이트보다 훨씬 큽니다. 그래서이 1071 오류가 발생합니다.

즉, 모든 문자 세트가 단일 바이트 표현이 아니기 때문에 문자 세트의 바이트 표현을 기반으로 문자 수를 계산해야합니다 (예상 한대로). utf8MySQL의 IE 는 문자 당 최대 3 바이트, 767 / 3255 문자, 및 utf8mb4최대 4 바이트 표현, 767/4 x 191 문자.

또한 MySQL로 알려져 있습니다

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

1

이 쿼리는 인덱스가 최대 길이를 위반하는 열을 감지하는 데 유용하다는 것을 알았습니다.

SELECT
  c.TABLE_NAME As TableName,
  c.COLUMN_NAME AS ColumnName,
  c.DATA_TYPE AS DataType,
  c.CHARACTER_MAXIMUM_LENGTH AS ColumnLength,
  s.INDEX_NAME AS IndexName
FROM information_schema.COLUMNS AS c
INNER JOIN information_schema.statistics AS s
  ON s.table_name = c.TABLE_NAME
 AND s.COLUMN_NAME = c.COLUMN_NAME 
WHERE c.TABLE_SCHEMA = DATABASE()
  AND c.CHARACTER_MAXIMUM_LENGTH > 191 
  AND c.DATA_TYPE IN ('char', 'varchar', 'text')

1

있는지 확인하시기 바랍니다 sql_mode같다

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

그렇다면

sql_mode=NO_ENGINE_SUBSTITUTION

또는

my.cnf 파일을 변경하여 서버를 다시 시작하십시오 (다음과 같이 입력).

innodb_large_prefix=on

1

필자의 경우 Linux 리디렉션 출력 / 입력 문자를 사용하여 데이터베이스를 백업 할 때이 문제가 발생했습니다. 따라서 아래 설명과 같이 구문을 변경합니다. 추신 : 리눅스 또는 맥 터미널을 사용합니다.

백업 (> 리디렉션없이)

# mysqldump -u root -p databasename -r bkp.sql

복원 (<redirect없이)

# mysql -u root -p --default-character-set=utf8 databasename
mysql> SET names 'utf8'
mysql> SOURCE bkp.sql

"지정된 키가 너무 깁니다. 최대 키 길이는 767 바이트입니다"라는 오류가 사라졌습니다.


1

인덱스 길이 및 MySQL / MariaDB


Laravel은 기본적으로 utf8mb4 문자 세트를 사용하는데 , 여기에는 데이터베이스에 "이모 지" 를 저장하는 기능이 포함 됩니다. 5.7.7 릴리스 이전의 MySQL 버전 또는 10.2.2 릴리스 이전의 MariaDB를 실행중인 경우, MySQL이 인덱스를 작성하기 위해 마이그레이션에서 생성 된 기본 문자열 길이를 수동으로 구성해야 할 수도 있습니다. AppServiceProvider 내 에서 Schema :: defaultStringLength 메소드 를 호출하여이를 구성 할 수 있습니다 .

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

또는 데이터베이스에 대해 innodb_large_prefix 옵션을 활성화 할 수 있습니다. 이 옵션을 올바르게 활성화하는 방법에 대한 지침은 데이터베이스 설명서를 참조하십시오.

블로그에서 참조 : https://www.scratchcode.io/specified-key-too-long-error-in-laravel/

공식 라 라벨 문서에서 참조 : https://laravel.com/docs/5.7/migrations


0

다음과 같은 것을 만드는 경우 :

CREATE TABLE IF NOT EXISTS your_table (
  id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
  name varchar(256) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY name (name)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

그것은 다음과 같아야합니다

CREATE TABLE IF NOT EXISTS your_table (
      id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
      name varchar(256) COLLATE utf8mb4_bin NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

그러나 코드에서 해당 열의 고유성을 확인하거나 새 열을 varchar 열의 MD5 또는 SHA1로 추가해야합니다.


3
그런 다음 고유 키가 손실되었습니다. 더 좋은 방법은 단순히 이름의 길이를 191로 줄이는 것입니다.
haudoing

1
네이티브 DB 기능인 경우 프로그래밍 방식으로 고유성을 확인해야하는 이유는 무엇입니까?
Paweł Tomkiel

0

접두사 제한으로 인해이 오류가 발생합니다. 767 바이트는 5.7 이전의 MySQL 버전에서 InnoDB 테이블에 대해 명시된 접두사 제한입니다. MyISAM 테이블의 길이는 1,000 바이트입니다. MySQL 버전 5.7 이상에서는이 제한이 3072 바이트로 증가했습니다.

오류가 발생한 서비스에서 다음을 실행하면 문제가 해결됩니다. MYSQL CLI에서 실행해야합니다.

SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=on;
SET GLOBAL innodb_large_prefix=on;

-1


불만족스러운 색인 필드의 CHARSET을 "latin1"로 변경하십시오. 즉 ALTER TABLE tbl CHANGE myfield myfield varchar (600) CHARACTER SET latin1 DEFAULT NULL;
latin1은 4 개 대신 1 개의 문자에 1 바이트를 사용합니다.


5
비 라틴 1 문자 를 삽입하려고하면 어떻게됩니까?
Paweł Tomkiel

4
이것은 최악의 일입니다. 그렇게하지 마십시오.
Sebas

1
내 경우에는 16 진수 문자로만 경로 이름을 저장하는 열에 ... 그래서 누군가에게 해결책이 될 수 있습니다. 그것은 당신이 무엇을 저장하고 싶은가에 달려 있습니다 ...
codewandler

latin1을 사용하는 것이 2016 AD의 해결책이 아니기 때문에 이것을 하향 투표해야했습니다. 2007 년에 데이터베이스를 latin1에서 utf8로 다시 변환해야했던 시간에 대해서는 여전히 끔찍한 악몽이 있습니다. 어. 예쁘지 않은. 조금도.
내기 Lamed

비트 코인 주소와 트랜잭션 ID를 저장하는 두 열의 고유 인덱스에서 동일한 문제가 발생했습니다. 이들은 항상 ASCII 문자이므로이 열에 latin1을 사용합니다. 공감.
alexg

-2

innodb_log_file_size최근에 변경 한 경우 작동했던 이전 값을 복원하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.